2016-04-27 20 views
1

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

+0

Haben Sie überprüft, um zu sehen, welche Größe Sie auf 'realloc' sind vorbei, wenn es scheitert? –

+1

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

+0

. 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

Antwort

0

Ich habe es herausgefunden. swap(to_delete, &list[size])

gerade benötigt swap(to_delete, &list[size - 1])

Hurray für dumme Fehler

2

Variablen als Wert übergeben wird in C.

Der Zeiger list gab del funktioniert geändert wird durch Realloc in der Funktion, aber der Zeiger außerhalb der Funktion wird nicht geändert. Das verursachte undefinierte Verhalten.

Pointer animal_list wird hier geführt:

del(animal_list, num_animals);  

die Kopie dieses Zeigers list, hier geändert wird:

list = realloc(list, sizeof(animal) * (size - 1)); 

Der ursprüngliche Zeiger animal_list bleibt unverändert.

Um dies zu lösen, geben Sie den Wert der neuen Zeigerliste zurück.

+0

Es ist erwähnenswert, dass Sie sich für einen Speicherverlust einrichten, indem Sie nicht eine 'tmp'-Variable verwenden, um die Rückgabe von' realloc' zuzuweisen, bevor der Erfolg bestätigt wird. Wenn 'realloc' fehlschlägt, gibt es 'NULL' zurück und Sie haben die Fähigkeit verloren, den Speicherblock 'freizugeben', auf den ursprünglich mit 'list' gezeigt wurde. –