【问题标题】:realloc fails in simple dict libraryrealloc 在简单的 dict 库中失败
【发布时间】:2022-01-27 20:51:34
【问题描述】:

我为一个使用 C 的快速项目编写了一个轻量级字典,但出现错误:realloc(): invalid next size。我知道这意味着我的堆以某种方式损坏了,但我不确定我做错了什么,看起来我的代码非常简单。

realloc 总是第四次访问失败,即dict->num_kvs = 4

下面是我的代码。它包括 dict 库以及使用它的函数。任何帮助将不胜感激

违规功能:

int* get_letter_frequencies(char* stream) { 

    Dict* dict = Dict_initialize();    

    for(int i = 0; i < strlen(stream); i++) {
        Dict_increment_or_add_key(dict, stream[i]);
    }

    int* to_return = Dict_get_values_array(dict);

    Dict_free();

    return to_return;
}

simple_dict.c(加上结构定义)


typedef struct kv_pair {
    char key;
    int value;
} KV_Pair;

typedef struct dict_ {
    struct kv_pair* kv_pairs;
    int num_kvs;
} Dict;

Dict* Dict_initialize() {
    Dict* to_return = malloc(sizeof(Dict));
    to_return->num_kvs = 0;
    to_return->kv_pairs = NULL;
    return to_return;
}

void Dict_free(Dict* dict) {
    free(dict->kv_pairs);
    free(dict);
}

int Dict_add_key(Dict* dict, char key) {
    dict->num_kvs++;
    printf("next size: %d\n", dict->num_kvs);
    dict->kv_pairs = realloc(dict->kv_pairs, dict->num_kvs * sizeof(KV_Pair));
    printf("realloc passed \n");

    dict->kv_pairs[dict->num_kvs].value = 1;

    return 0;
}

int Dict_find_key(Dict* dict, char key){

    for(int i = 0; i < dict->num_kvs; i++) {
        char cur_key = dict->kv_pairs[i].key;
        if(cur_key == key) {
            return i;
        }
    }

    return -1;
}

int Dict_increment_or_add_key(Dict* dict, char key) {

    int key_index = Dict_find_key(dict, key);

    if(key_index == -1) {
        Dict_add_key(dict, key);
    } else {
        dict->kv_pairs[key_index].value++;
    }


}

int* Dict_get_values_array (Dict* dict) {
    int* to_return = malloc(dict->num_kvs * sizeof(int));

    for(int i = 0; i < dict->num_kvs; i++) {
        to_return[i] = dict->kv_pairs[i].value;
    }

    if(dict->num_kvs > 26) {
        printf("more than 26 kvs: %d", dict->num_kvs);
    }

    return to_return;
}

【问题讨论】:

  • 内存损坏的可悲之处是程序明显失败的地方几乎永远不会出现错误。
  • 换句话说,为了让其他人有机会找到问题,您需要提供可以重现问题的完整最小代码。见:minimal reproducible example。也就是说,包括main 以及设置和重现问题所需的任何其他代码。
  • dict-&gt;kv_pairs[dict-&gt;num_kvs].value = 1; 访问越界内存。 dict-&gt;num_kvs 元素的数组分配的最大有效索引为 dict-&gt;num_kvs - 1
  • 我觉得自己很傻。非常感谢你们的帮助。这确实解决了问题
  • 另外,我认为你犯了一个小错误,我认为 for 循环中的第二个语句需要是 *chp;,而不是 chp;,因为我们正在寻找字符为 0 ,而不是地址

标签: c memory-management memory-leaks heap-memory realloc


【解决方案1】:

当您尝试添加第一个元素时,将dict-&gt;num_kvs 递增到1,然后分配一个元素。然后这一行:

dict->kv_pairs[dict->num_kvs].value = 1;

它将尝试写入[1] 元素,而不是[0] 元素。这是越界了。你应该使用:

dict->kv_pairs[dict->num_kvs-1].value = 1;

PS:如果您使用的是 GCC 或 Clang,AddressSanitizer 是帮助您检测此类错误的绝佳工具。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 2013-09-19
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多