【问题标题】:Deallocation of memory in arrays数组中的内存释放
【发布时间】:2017-07-04 05:46:41
【问题描述】:

我已经完成了一个程序,它可以打开文件(读取二进制文件),并将所有单词(在文件中)保存在一个 char 数组中(根据单词的长度动态分配)。
这是代码:

char **leggi_stringhe(const char *filename, size_t *size) {
    FILE *f = fopen(filename, "rb");
    if (f == NULL) {
        *size = 0;
        return NULL;
    }

    int x;

    if (fread(&x, 1, 4, f) != 4) {
        *size = 0;
        return NULL;
    }

    char **stringhe = malloc((x) * sizeof(char));

    for (int i = 0; i < x; i++) {
        int z = 0;
        if (fread(&z, 1, 4, f) != 4) {
            *size = 0;
            return NULL;
        }

        stringhe[i] = malloc((z)* sizeof(char));
        if (fread(stringhe[i], 1, z, f) != z) {
            *size = 0;
            return NULL;
        }
        stringhe[i][z] = 0;
    }
    *size = x;
    fclose(f);
    return stringhe;
}

int main(void) {
    size_t t;
    char **a = leggi_stringhe("file1.bin", &t);

    for (int i = 0; i < t; i++)
        free(a[i]);
    free(a);;
}

该程序有效,但我在内存释放方面遇到了问题。 调用leggi_stringhe函数后,变量a包含:

a[0] = "first"
a[1] = "second"
a[2] = "third"

但是当我尝试释放整个 a 变量时,调试器会停止并发出警告。
我受到这个问题的启发,编写了我的代码Using Dynamic Memory allocation for arrays,但不明白为什么在尝试解除分配时会出现此错误。

【问题讨论】:

  • 请注意sizeof(char) 始终为 1。
  • 刚刚看到:sizeof(char *) 应该是
  • fread(&amp;z, 1, 4, f)?为什么你认为z 是四个字节?您还隐含地假设您的数据文件来自与您正在处理的机器具有相同字节序的机器。
  • 此代码除了提到的错误之外还有其他基本问题。见Correctly allocating multi-dimensional arrays

标签: c arrays string memory stdio


【解决方案1】:

您对malloc 的初次调用是错误的。您为x 字符 分配空间,而不是为指向char 的指针。

您在循环中的第二次调用是错误的,因为您没有为终止符分配空间。

最后,与您提出的问题无关,但如果循环内的 fread 调用失败,您将出现内存泄漏。

【讨论】:

  • 致 OP:@M41Npain,请检查 malloc() 是否返回 NULL。这段代码可能太多了,但这是你必须养成的习惯
  • @IharobAlAsimi cplusplus.com say 如果函数未能分配请求的内存块,则返回一个空指针。它指的是什么?
  • @M41Npain 在 C 中 NULL 是空指针的标准符号。如果在您的情况下,在第一次调用 malloc 后,stringhe 等于 NULL,则分配失败,您不应继续使用指针。
【解决方案2】:

您的代码存在一些问题:

  • 这一行:

    char **stringhe = malloc((x) * sizeof(char));
    

    需要:

    char **stringhe = malloc((x) * sizeof(char*)); /* or sizeof *stringhe */
    

    因为您需要为stringhe 分配x char* 指针。

  • 在您的第一个 for 循环中,您没有添加 +1 作为空终止符。它需要改为:

    stringhe[i] = malloc(z+1); /* sizeof(char) = 1 */
    
  • 您需要检查malloc() 的返回。如果不成功,它可以返回NULL。您可以通过简单地检查if (ptr == NULL) 来完成此操作,然后退出程序。允许失败的malloc() 在程序中继续是不安全的。

  • for (int i = 0; i &lt; t; i++)intsize_t 进行比较。这应该是for (size_t i = 0; i &lt; t; i++)

【讨论】:

  • 我没有在stringhe[i] = malloc((z)* sizeof(char)); 中添加 +1,因为在 malloc 之后我在调试器中看到,malloc 函数总是分配更多必要的空间,事实上,然后我添加了 stringhe[i][z]= 0; 到把剩下的切掉
  • @M41Npain 在分配char* 指针时,在使用malloc() 时添加额外的+1 总是安全的。它现在可能有效,但将来如果您不这样做,并且malloc() 没有为\0 分配足够的空间,那么您将访问超出分配范围的内容。
  • @M41Npain 在处理堆分配时,最好是安全而不是抱歉。我很高兴能帮上忙 :)。
猜你喜欢
  • 1970-01-01
  • 2016-01-08
  • 2015-09-05
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-02
  • 2014-09-27
相关资源
最近更新 更多