首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >房地产收缩失败

房地产收缩失败
EN

Stack Overflow用户
提问于 2016-04-27 18:48:47
回答 2查看 186关注 0票数 1

我不确定我在这里是否遗漏了什么,但是realloc()在试图收缩动态结构数组时失败了,其大小无效。我已经将非必要的函数从代码中删除为post:

代码语言:javascript
复制
#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
}

我是不是不正确地缩小了数组?我被困在这里了

编辑:我知道realloc()会失败,因为它表现得非常出色,并且失败了,给出了这样的消息:

代码语言:javascript
复制
*** 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)

按照2501的建议,我重写了函数以将列表传递回调用函数,但是它并没有改变程序在同一地点中止的情况。

此外,gdb在计算该行时给出了如下内容:

代码语言:javascript
复制
realloc: Assertion `ptr == alloc_last_block' failed!

编辑2:经过一系列的调试,导致堆损坏的是swap(),但我不知道原因。我按照建议重写了swap(),但在紧接其后的realloc()失败,而紧接在前面的realloc()则没有。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-27 22:24:31

弄明白了。swap(to_delete, &list[size])

只是需要成为swap(to_delete, &list[size - 1])

为愚蠢的错误欢呼

票数 0
EN

Stack Overflow用户

发布于 2016-04-27 19:13:34

变量在C中通过值传递。

传递给函数list的指针del由函数中的realloc更改,但函数外部的指针没有更改。引起的未定义行为。

指针animal_list在这里传递:

代码语言:javascript
复制
del(animal_list, num_animals);    

指针list的副本在这里更改:

代码语言:javascript
复制
list = realloc(list, sizeof(animal) * (size - 1));

原始指针animal_list保持不变。

若要解决此问题,请返回新指针列表的值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36898413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档