Ich bin nicht sicher, ob ich hier etwas fehlt, aber Realloc() schlägt mit ungültiger Größe, wenn ich versuche, ein dynamisches Array von Strukturen zu verkleinern. ive getrimmt die nicht wesentlichen Funktionen aus dem Code zu buchen:Realloc schlägt auf Schrumpf
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char const file_name[] = "animals.dat";
typedef enum {
false, true } bool;
typedef struct {
char month;
char day;
short year;
} date;
typedef struct {
bool parvo_vacc;
bool fip_vacc;
bool rabies_vacc;
bool has_mc;
bool worm_vacc;
} md_history;
typedef struct {
int id;
char age;
char name[25];
char description[50];
md_history medical;
date intake_date;
date adopt_date;
} animal;
void lookup(animal* list, int size);
int compare(const void* this, const void* that);
void sort(animal* list, int size);
//this brings the new name back with it, since it isnt saved correctly
//in the new animal
animal* add(char* name);
void del(animal* list, int size);
void print_results(animal** results, int size);
void print_animal(animal* print);
void swap(animal* this, animal* that);
int main(int argc, char **argv)
{
FILE* readfile = fopen(file_name, "r");
if (readfile == NULL)
{
printf("Error file not found: %s\n", file_name);
}
//read data using fread(), keeping track of the number
//of bytes missed
int num_animals = 0;
fread(&num_animals, sizeof(int), 1, readfile);
animal* animal_list = (animal*) calloc(num_animals, sizeof(animal));
int errnum = num_animals - (fread(animal_list,
sizeof(animal), num_animals, readfile));
if (errnum > 0)
{
printf("Read encountered %d errors", errnum);
}
fclose(readfile);
char c;
char* name = malloc(sizeof(char) * 25);
//switch statements dont allow declarations for whatever reason
int x;
while(c != 'q')
{
printf("Options: (l)ookup (s)ort (a)dd (d)elete (p)rint (q)uit (e)dit\n");
scanf(" %c", &c);
switch (c)
{
case 'l':
lookup(animal_list, num_animals);
break;
case 's':
sort(animal_list, num_animals);
break;
case 'p':
for (x = 0; x < num_animals; x++)
{
print_animal(&animal_list[x]);
}
break;
case 'a':
//after dealing with lots of iostream errors trying to
//set the name field in add(), i decided to just return
//the new name to here and strcpy it
animal_list = realloc(animal_list, sizeof(animal) * (num_animals + 1));
swap(&animal_list[num_animals], add(name));
strcpy(animal_list[num_animals].name, name);
num_animals++;
//memory leak here, since switch statements dont allow
//declarations, i cant save the new animal pointer to a temp
//var so it can be deleted
break;
case 'd':
del(animal_list, num_animals);
num_animals--;
break;
}
}
return 0;
}
void swap(animal* this, animal* that)
{
animal temp;
temp.id = this->id;
strcpy(temp.name, this->name);
temp.age = this->age;
strcpy(temp.description, this->description);
temp.medical.fip_vacc = this->medical.fip_vacc;
temp.medical.has_mc = this->medical.has_mc;
temp.medical.parvo_vacc = this->medical.parvo_vacc;
temp.medical.rabies_vacc = this->medical.rabies_vacc;
temp.medical.worm_vacc = this->medical.worm_vacc;
temp.intake_date.day = this->intake_date.day;
temp.intake_date.month = this->intake_date.month;
temp.intake_date.year = this->intake_date.year;
temp.adopt_date.day = this->adopt_date.day;
temp.adopt_date.month = this->adopt_date.month;
temp.adopt_date.year = this->adopt_date.year;
this->id = that->id;
strcpy(this->name, that->name);
this->age = that->age;
strcpy(this->description, that->description);
this->medical.fip_vacc = that->medical.fip_vacc;
this->medical.has_mc = that->medical.has_mc;
this->medical.parvo_vacc = that->medical.parvo_vacc;
this->medical.rabies_vacc = that->medical.rabies_vacc;
this->medical.worm_vacc = that->medical.worm_vacc;
this->intake_date.day = that->intake_date.day;
this->intake_date.month = that->intake_date.month;
this->intake_date.year = that->intake_date.year;
this->adopt_date.day = that->adopt_date.day;
this->adopt_date.month = that->adopt_date.month;
this->adopt_date.year = that->adopt_date.year;
that->id = temp.id;
strcpy(that->name, temp.name);
that->age = temp.age;
strcpy(that->description, temp.description);
that->medical.fip_vacc = temp.medical.fip_vacc;
that->medical.has_mc = temp.medical.has_mc;
that->medical.parvo_vacc = temp.medical.parvo_vacc;
that->medical.rabies_vacc = temp.medical.rabies_vacc;
that->medical.worm_vacc = temp.medical.worm_vacc;
that->intake_date.day = temp.intake_date.day;
that->intake_date.month = temp.intake_date.month;
that->intake_date.year = temp.intake_date.year;
that->adopt_date.day = temp.adopt_date.day;
that->adopt_date.month = temp.adopt_date.month;
that->adopt_date.year = temp.adopt_date.year;
}
void del(animal* list, int size)
{
printf("Delete by: (n)ame (i)d\n");
char c;
while (getchar() != '\n');
scanf("%c", &c);
animal* to_delete = NULL;
if (c == 'n')
{
printf("Enter name to delete: ");
char to_search[25];
while (getchar() != '\n');
scanf(" %s", to_search);
int x;
for (x = 0; x < size; x++)
{
if (strcmp(to_search, list[x].name) == 0)
{
to_delete = &list[x];
}
}
}
if (c == 'i')
{
printf("Enter ID to delete: ");
int to_search;
while (getchar() != '\n');
scanf("%d", &to_search);
int x;
for (x = 0; x < size; x++)
{
if (to_search == list[x].id)
{
to_delete = &list[x];
}
}
}
swap(to_delete, &list[size);
list = realloc(list, sizeof(animal) * (size - 1)); //fails right here
}
bin ich das Array falsch schrumpfen? im ziemlich hier stapfte
EDIT: Ich weiß, realloc() schlägt fehl, weil es so spektakulär macht und bricht, diese Nachricht zu geben:
*** Error in `./final': realloc(): invalid next size: 0x0000000000c11250 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x77725)[0x7f6ae72ba725]
/lib/x86_64-linux-gnu/libc.so.6(+0x82bfa)[0x7f6ae72c5bfa]
/lib/x86_64-linux-gnu/libc.so.6(+0x85179)[0x7f6ae72c8179]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x22f)[0x7f6ae72c6e6f]
./final[0x401d3e]
./final[0x400b82]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f6ae7263830]
./final[0x400849]
======= Memory map: ========
00400000-00403000 r-xp 00000000 08:01 3146140 /home/destrovel/cppwork/final
00602000-00603000 r--p 00002000 08:01 3146140 /home/destrovel/cppwork/final
00603000-00604000 rw-p 00003000 08:01 3146140 /home/destrovel/cppwork/final
00c10000-00c31000 rw-p 00000000 00:00 0 [heap]
7f6ae0000000-7f6ae0021000 rw-p 00000000 00:00 0
7f6ae0021000-7f6ae4000000 ---p 00000000 00:00 0
7f6ae702d000-7f6ae7043000 r-xp 00000000 08:01 1069105 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f6ae7043000-7f6ae7242000 ---p 00016000 08:01 1069105 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f6ae7242000-7f6ae7243000 rw-p 00015000 08:01 1069105 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f6ae7243000-7f6ae7403000 r-xp 00000000 08:01 1049974 /lib/x86_64-linux-gnu/libc-2.23.so
7f6ae7403000-7f6ae7602000 ---p 001c0000 08:01 1049974 /lib/x86_64-linux-gnu/libc-2.23.so
7f6ae7602000-7f6ae7606000 r--p 001bf000 08:01 1049974 /lib/x86_64-linux-gnu/libc-2.23.so
7f6ae7606000-7f6ae7608000 rw-p 001c3000 08:01 1049974 /lib/x86_64-linux-gnu/libc-2.23.so
7f6ae7608000-7f6ae760c000 rw-p 00000000 00:00 0
7f6ae760c000-7f6ae7632000 r-xp 00000000 08:01 1049970 /lib/x86_64-linux-gnu/ld-2.23.so
7f6ae77f9000-7f6ae77fc000 rw-p 00000000 00:00 0
7f6ae782e000-7f6ae7831000 rw-p 00000000 00:00 0
7f6ae7831000-7f6ae7832000 r--p 00025000 08:01 1049970 /lib/x86_64-linux-gnu/ld-2.23.so
7f6ae7832000-7f6ae7833000 rw-p 00026000 08:01 1049970 /lib/x86_64-linux-gnu/ld-2.23.so
7f6ae7833000-7f6ae7834000 rw-p 00000000 00:00 0
7ffd8a23b000-7ffd8a25c000 rw-p 00000000 00:00 0 [stack]
7ffd8a331000-7ffd8a333000 r--p 00000000 00:00 0 [vvar]
7ffd8a333000-7ffd8a335000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
ich die Funktion neu geschrieben um die Liste an die aufrufende Funktion zu übergeben, wie Vorschlag von 2501, aber es hat nicht das Programm an derselben Stelle auch
Abbruch ändern, gibt gdb dies, wenn diese Zeile Auswertung:
realloc: Assertion `ptr == alloc_last_block' failed!
EDIT 2: achtern Er ist ein Haufen Debugging, es ist der Swap(), der den Haufen verdirbt, aber ich kann nicht herausfinden, warum. i schrieb swap(), wie vorgeschlagen, sondern ein realloc() sofort aus, nachdem während eines realloc() unmittelbar vor nicht
Haben Sie überprüft, um zu sehen, welche Größe Sie auf 'realloc' sind vorbei, wenn es scheitert? –
Wie haben Sie festgestellt, dass 'realloc()' fehlgeschlagen ist? Die Rückgabe von 'NULL' bedeutet nicht unbedingt, dass es fehlgeschlagen ist. 'realloc()' kann 'NULL' für eine 0-Zuweisung sowie für nicht genügend Speicher zurückgeben, – chux
. Sie sollten auf diese Weise nicht realloc aufrufen. Sie überschreiben die Liste, wenn die Neuzuweisung fehlschlägt und Sie den ursprünglichen Zeiger verloren haben. – bruceg