为什么free在我的代码中时会导致错误,而在不存在时一切运行正常?

问题描述

我的程序在运行时接受任意数量的单词,并将它们存储在动态大小的单词数组中。

当前,我的程序运行良好,除了使用free()释放临时双指针temp的内存外。我不太确定为什么要这样做,因为我认为如果不使用它会导致错误

int wordSize = 10,arrSize = 1,i = 0;
char **stringArr,**temp;
char *input;

stringArr = malloc(arrSize * sizeof(char *));

puts("Accepting input...");

for (;;) {
    if (i >= arrSize) {
        arrSize += 1;
        temp = realloc(stringArr,arrSize * sizeof(char *));

        if (temp != NULL) {
            stringArr = temp;
            free(temp); // This is the line that is giving me issues; removing it works
        } else {
            puts("Could not allocate more memory");
            return 0;
        }
    }

    stringArr[i] = malloc(sizeof(input));
    input = malloc(wordSize * sizeof(char));
    scanf("%10s",input);

    if (strcmp(input,"END")) {
        strcpy(stringArr[i],input);
        i++;
    } else
        break;
       
}
free(stringArr);

在程序的底部,我使用free()没有任何问题。在这里,它如何工作正常,但在程序的较早版本中没有。

我觉得我缺少关于free()的工作方式的信息。

注意:这是我第一个实现malloc()realloc()的程序,因此我只是习惯于它们的工作方式。如果您知道实现我正在执行的操作的更好方法,请随时描述。

解决方法

free(temp);行引起错误(以后),因为在上一行stringArr = temp;中,您正在分配存储在{{ 1}}指向temp指针中的指针。因此,当您释放stringArr指向的内存时,您也释放了temp指向的内存,因为它是相同内存块。将指针的值从一个变量复制到另一个不会进行内存的(单独)副本。

省略stringArr行是正确的,因为稍后会在free(temp);调用中释放该内存。

,

重新分配成功后,您不得释放重新分配的阵列。如果这样做,代码将修改此已释放的块,该块具有未定义的行为,并且在以后尝试重新分配或释放此块时,您将具有进一步的未定义的行为。

还请注意以下几点:

  • 无需预先分配大小为stringArr的{​​{1}}。只需将1初始化为stringArr,并将0初始化为arrSize0可以使用空指针,其行为类似于realloc()

  • malloc()是错误的:它将根据目标体系结构上的指针大小而不是stringArr[i] = malloc(sizeof(input));个字节来分配大小为4或8的char数组

  • 如果11是一个单词的最大长度,则应为空终止符再分配一个字节。 wordSize中的10必须与%10s的值匹配,这很麻烦,因为没有简单的方法将其作为变量传递给wordSize

  • 您不检查scanf()的返回值,如果文件过早结束,则会导致不确定的行为。

  • 您有内存泄漏:scanf()为每次迭代分配,但从未释放,释放input而不释放其元素指向的字符串会使它们不可访问。

使用本地数组尝试使用stringArr读取单词,然后仅分配字符串,如果成功,则重新分配数组会更有效。

这是修改后的版本:

scanf()