【问题标题】:Invalid read - Valgrind and C无效读取 - Valgrind 和 C
【发布时间】:2014-08-29 00:01:31
【问题描述】:

C 和 Valgrind 以及手动内存管理的新手,我无法找到运行 Valgrind 时遇到的错误。我有这个从用户那里获取字符串的函数:

char **get_fragments_from_user(){
    // No more than 20k strings containing at most 1k characters
    char **strings = malloc(20000 * sizeof(char *));

    char tempstring[MAX_INPUT]; //MAX_INPUT = 1001
    int count = 0;
    while(true){
        printf("\n> ");
        fgets(tempstring, MAX_INPUT, stdin);
        if((strlen(tempstring) > 0) && (tempstring[strlen(tempstring) - 1] == '\n')){
            tempstring[strlen(tempstring) - 1] = '\0';
        }
        if(tempstring[0] == 'q') break;
        strings[count] = malloc(sizeof(char) * (strlen(tempstring)+1));
        strcpy(strings[count], tempstring);
        count++;
    }
    int i = 0;
    char **fstrings = malloc((count)*sizeof(char *)); // count+1 needed? Something I tried removing while debugging
    for(i = 0; i < count; i++){
        fstrings[i] = malloc(sizeof(char) * (strlen(strings[i])+1));
        strcpy(fstrings[i], strings[i]);
        free(strings[i]);
    }
    free(strings);
    return fstrings;
}

这里的想法只是获取字符串并将它们放入数组中。我最初分配了一个足够大的数组,以适应可以输入的最大字符串数(20,000),但我随后调整了数组的大小,以便分配的内存不会超过每个字符串所需的内存。我对上面的代码有点尴尬,因为它没有我用另一种语言编写的任何代码那么干净,但这是我第一次通过。

然后,当我尝试使用此函数计算数组中的字符串数时,我从 Valgrind 得到“大小为 8 的无效读取”:

int lengthOf(char **arr){
    int i = 0;
    while(arr[i] != NULL){
        i++;
    }
    return i;
}

我很确定这是由于取消引用的指针或其他原因造成的,但我一生都找不到它,而且我一直在看这段代码一个小时左右。

【问题讨论】:

  • 建议,char **fstrings = calloc(count+1, sizeof(char *));
  • 加号:return fstrings; -->> fstrings[i] = NULL;
  • 好的,所以要 count+1 并将 malloc 变成 calloc 已经摆脱了我原来遇到的问题,但我现在遇到了一些其他问题,但我会看看我是否可以首先通过它们。另一个大小为 1 的无效读取。
  • @wildplasser:为什么要这样做?我的直觉是它确保 lengthOf 函数能够正常工作,但我不完全确定这是否正确。
  • lengthof() 函数计数,直到它在数组中看到 NULL。你没有在里面放一个 NULL,那为什么要放一个呢?

标签: c arrays memory memory-management valgrind


【解决方案1】:

所以,我认为问题在于我没有分配足够的内存来存储整个数组。

而不是做:

malloc(count * sizeof(char *));

我应该分配 count+1,所以要么:

malloc((count + 1) * sizeof(char *))

calloc((count + 1), sizeof(char *));

【讨论】:

  • 显然没有必要将每个字符串复制两次,您可以简单地通过 fstrings[ i] = strings [i] 分配指针,避免复制循环中的 malloc、strcpy 和 free。字符串/fstrings 需要以 NULL 条目终止,因此要么使用 calloc,要么使用 malloc 并分配给 strings[count] = 0 & fstrings[count]。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2017-04-09
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多