【问题标题】:Realloc struct array as a function parameter yields segmentation fault?Realloc 结构数组作为函数参数会产生分段错误?
【发布时间】:2017-03-17 23:44:45
【问题描述】:

在询问之前我已经搜索了很多,但我似乎无法使这个功能工作。
我有这个 array of structs 有 2 个字符串 (char*) 以及添加新结构的函数put()
除非在这种情况下键已经存在,否则它只会用新的值覆盖当前值。

尽管我通过引用传递数组并且没有在函数中制作本地副本,但内存仍然损坏(Segmentation Fault)

源代码是在Ubuntu 15.10最新版本的gcc上编译的。
提前感谢你们的帮助!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 3

struct store{
    char *key;
    char *value;
};

void put(char *key, char *value, struct store **store, int size){
    int i, found;
    struct store *temp = realloc(*store, (size + 1) * sizeof(struct store));
    for(i = 0; i < size; ++i){
        if(strcmp(key, store[i]->key) == 0){ //Key found, overwrite new value.
            store[i]->value = strdup(value); //Assume that every value is null terminated
            found = 1;
            break;
        }
    }
    if(found) return;

    *store = temp;
    if(!store){ 
         perror("realloc failed");
         exit(EXIT_FAILURE);
    }    
    store[size]->key = strdup(key); //New element
    store[size]->value = strdup(value);
    return;
}

int main(){
    int i = 0;
    struct store *store = malloc(N * sizeof(struct store));
    if(!store){ 
       perror("malloc failed");
       exit(EXIT_FAILURE);
    }
    store[0].key = strdup("123a");
    store[1].key = strdup("456b");
    store[2].key = strdup("789c");
    store[0].value = strdup("John");
    store[1].value = strdup("Sam");
    store[2].value = strdup("Mary");

    for(i = 0; i < N; ++i)
        printf("%s, %s\n\n",store[i].key,store[i].value); //This works fine

    put("123a","Jim",&store,N);
    for(i = 0; i < N; ++i)
        printf("%s, %s\n\n",store[i].key,store[i].value);

    put("653a","Tom",&store,N);
    for(i = 0; i < N+1; ++i)
        printf("%s, %s\n\n",store[i].key,store[i].value);

    return 0;
}

【问题讨论】:

    标签: c arrays struct realloc


    【解决方案1】:
    struct store *temp = realloc(*store, (size + 1) * sizeof(struct store));
    for(i = 0; i < size; ++i){
        if(strcmp(key, store[i]->key) == 0){ //Key found, overwrite new value.
            store[i]->value = strdup(value); //Assume that every value is null terminated
            found = 1;
            break;
        }
    }
    if(found) return;
    
    *store = temp;
    

    如果找到密钥,则不要将 temp 分配给 *storerealloc 可以将分配的内存移动到一个全新的地址,从而留下*store 一个悬空指针。而且你真的应该检查temp 也不是空的。

    还有你滥用store的问题。 store 是您传递给函数的指针的地址,而不是数组的第一个元素。

    你需要像(*store)[i]这样索引数组。

    【讨论】:

    • @wing - 否。因为realloc 将在失败时返回 NULL,但不会释放您传递给它的内容。所以如果你直接分配内存会泄漏。你需要中间指针。
    • @wing - 从语法上讲,这是正确的,但并不总是如此。你当然不应该在 realloc 之前释放。这将使您的程序具有未定义的行为。只需检查 temp 不是 NULL,如果没有将其分配给 *store。将调用realloc的行移到循环之后。
    • @wing - 查看我的编辑。请回滚您自己的编辑。当您将他们提出的修复合并到您的问题代码中时,它会使答案出错。
    • @wing - 是的。现在,您的循环将 store 视为指针数组,但事实并非如此。
    • @wing - 是的,就是这样。
    猜你喜欢
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2013-10-27
    • 1970-01-01
    • 2021-04-07
    • 2015-02-20
    • 1970-01-01
    相关资源
    最近更新 更多