【问题标题】:What is wrong with how I'm dynamically allocating space for this 2d array?我如何为这个二维数组动态分配空间有什么问题?
【发布时间】:2020-02-15 19:15:06
【问题描述】:

我正在尝试创建一个 2D 数组,该数组将能够将 .txt 文件的每个字符存储为 2D 数组中的一个元素。

如何为它动态分配空间?

这就是我到目前为止所做的 malloc 它。 (这是从 GeeksForGeeks 复制的)

char *arr[rownum2];

for (i = 0; i < rownum2; i++) {
    arr[i] = (char *)malloc(colnum * sizeof(char));

但是,我认为这是我程序中与内存相关的严重问题的根源,我也被告知其中某些部分是不必要的。

请问在这种特定场景下,我能否找到最合适的方式为二维数组动态分配内存?

【问题讨论】:

  • 小sn-p看似合理,但没有上下文。
  • 不需要的部分是:转换malloc提供的值,sizeof(char)定义为1。所以arr[i] = malloc(colnum);

标签: c arrays pointers memory malloc


【解决方案1】:

您发布的代码“OK”,只要您记得在分配的内存上调用free(),稍后在您的代码中,如下所示:

for (i=0;i<rownum2;i++) free(arr[i]);

...我还被告知有些部分是不必要的。

explicit cast is unnecessary,所以,而不是:

arr[i] =  (char *)malloc(colnum*sizeof(char));

只需使用:

arr[i] =  malloc(colnum*sizeof(char));

严格来说,sizeof(char) 也是不必要的(char 的大小始终为1),但为了清楚起见,您可以保留它。

【讨论】:

  • 如果我稍后不调用 free 会发生什么,这会在我的函数中弄乱指针和内存位置的东西(我知道我没有给出很多上下文,但是您从经验中有何看法)?这与删除二维数组中的元素本质上是否相同,因为我将无法再访问它们?
  • 是的 - 调用 free 释放分配的内存,然后尝试访问该内存的任何部分是一个错误(或充其量是未定义的行为)。如果您在使用完内存后没有调用free,那么您就有所谓的“内存泄漏”——如果您继续这样做,您的系统很快就会耗尽内存。
【解决方案2】:

从技术上讲,它不是二维数组,而是数组数组。不同的是,你不能用不同大小的线制作二维数组,但你可以用你的数组数组来做。

如果你不需要它,你可以分配rownum2*colnum元素并以arr[x+colnum*y]访问每个元素(它经常使用,因为所有数据都保存在一个地方,减少CPU缓存负载和一些系统内部存储需求每个分配的块的每个指针)。

此外,即使是不同大小的线数组也可以放入一维数组并像二维一样访问(至少,如果它们不改变大小甚至 RO)。您可以分配char body[total_size],读取整个数组,分配char* arr[rownum2] 并设置每个arr[i]=body+line_beginning_offset

顺便说一句,不要忘记没有实际的 C 字符串,因为它们不是以空值结尾的。您将需要一个额外的空项列。如果存储 ASCII 艺术,二维数组是一个很好的解决方案。

【讨论】:

    【解决方案3】:

    我在您的代码中看到的唯一严重问题是您正在转换malloc(3) 的返回值,并且您可能也忘记了#include &lt;stdlib.h&gt;(这是一种危险的鸡尾酒),这样,您正在破坏使用您在malloc(3) 之前进行的转换的调用的返回值。让我解释一下:

    • 首先,您有(或没有,但我不得不猜测)64 位架构(现在很常见)并且系统中的指针是 64 位宽,而int 整数是 32 位宽。
    • 您可能忘记在您的代码中使用#include &lt;stdlib.h&gt;(这也是我必须猜测的),因此编译器假设malloc(3) 实际上是一个返回int 的函数(这是C 中的遗留问题,如果您没有为编译单元外部的函数提供原型),因此编译器正在生成代码以从 malloc(3) 函数获取 32 位值,而不是 64 位指针(可能,但我必须也猜一猜)malloc(3) 实际返回。
    • 您正在将 int 32 位值(已经不正确)转换为 64 位指针(更不正确,但我不得不猜测......),对整数值和指针之间的类型转换发出任何警告以消失,并且进行强制转换时保持静音(编译器假定,作为一个聪明的程序员,您是故意将强制转换放在那里的,并且您知道自己在做什么)
    • 第一个(未定义的行为)返回值是(未定义的行为)刚刚切入 32 位,然后转换(从 intchar *,具有更多未定义的行为)以在您的代码中使用。这使得从malloc(3) 返回的原始指针在重新解释并转换为(char *) 时将具有完全不同的值。这会使您的指针指向不同的位置,并在执行时中断您的程序。

    您的代码应该类似于(再次,必须使用 sn-p,因为您的代码不完整):

    #include <stdlib.h> /* for malloc() */
    
    /* ... */
    
    char *arr[rownum2];
    
    for (i = 0; i < rownum2; i++) {
        arr[i] = malloc(colnum); /* sizeof(char) is always 1 */
    

    最后我需要给你一个建议:

    请阅读(并关注)how to create a minimal, verifiable example 页面,因为您可能缺少 #include 错误,我不得不猜测......我们必须猜测这里会发生什么。 这是您必须从这个答案中学到的最重要的事情。 发布完整、可编译和可验证的代码(即,您可以在发布之前检查失败的代码,而不是您在哪里选择的 sn-p你猜这个问题可能是)。您发布的代码确实不允许任何人验证它为什么会失败,因为它必须完成(并且可能修复)才能使其可执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多