释放二维arrays – 检测到堆腐蚀

编辑:对不起伙计们,我忘了提到这是在VS2013中编码的。

我有一个全局声明的结构:

typedef struct data //Struct for storing search & sort run-time statistics. { int **a_collision; } data; data data1; 

然后我分配我的记忆:

 data1.a_collision = (int**)malloc(sizeof(int)*2); //Declaring outer array size - value/key index. for (int i = 0; i < HASH_TABLE_SIZE; i++) data1.a_collision[i] = (int*)malloc(sizeof(int)*HASH_TABLE_SIZE); //Declaring inner array size. 

然后我初始化所有元素:

 //Initializing 2D collision data array. for (int i = 0; i < 2; i++) for (int j = 0; j < HASH_TABLE_SIZE; j++) data1.a_collision[i][j] = NULL; 

最后,我希望释放记忆(失败)。 我没有成功地尝试过关于SO的一些答案。

 free(data1.a_collision); for (int i = 0; i < HASH_TABLE_SIZE; i++) free(data1.a_collision[i]); 

在第一个空闲语句中给出了检测到堆损坏错误。 有什么建议?

您的代码中存在多个错误。 逻辑错误如何为二维数组分配内存以及一些错别字。

从代码中的注释“外部数组大小 – 值/键索引”看起来你想要为“2 * HASH_TABLE_SIZE”大小的2D数组分配内存,而从你的代码中为for loop breaking条件“i

分配记忆:

让我假设你想为“2 * HASH_TABLE_SIZE”分配内存,你可以为不同的维度应用相同的概念。

维度“2 * HASH_TABLE_SIZE”表示两行和HASH_TABLE_SIZE列。 正确的分配步骤如下:

步骤1:首先创建一个长度等于行数的int指针数组。

 data1.a_collision = malloc(2 * sizeof(int*)); // 2 rows ^ ^ you are missing `*` 

这将创建一个两个大小的int指针数组( int* ),在外部数组分配的代码中,您为两个int对象分配了内存为2 * sizeof(int)而您需要内存来存储地址。 你需要分配的总内存字节应该是2 * sizeof(int*) (这是错误的拼写错误)。

您可以将以上分配图片视为:

  343 347 +----+----+ data1.a_collision---►| ? | ? | +----+----+ 
  1. ? – 表示垃圾值,malloc不初始化分配内存
  2. 它分配了两个存储单元,每个存储单元可以存储int地址
  3. 在图片中我假设int *的大小是4个字节。

另外,你应该注意到我没有从malloc函数中对返回的地址进行类型转换,因为它是隐式的类型无效*是通用的并且可以分配给任何其他类型的指针类型(事实上在C中我们应该避免类型转换,你应该从Do中读取更多内容) 我转换了malloc的结果? )。

现在,步骤-2:为每个行分配内存,作为数组中需要的长度列数的数组= HASH_TABLE_SIZE。 所以你需要循环行数(不是HASH_TABLE_SIZE)来为每行分配数组,如下所示:

 for(int i = 0; i < 2; i++) // ^^^^ notice data1.a_collision[i] = malloc(HASH_TABLE_SIZE * sizeof(int)); // ^^^^^ 

现在,在每行中,您将为长度为HASH_TABLE_SIZE的整数数组存储int ,您需要内存字节= HASH_TABLE_SIZE * sizeof(int) 。 您可以将其描绘为:

  data1.a_collision = 342 | ▼ 201 205 209 213 +--------+ +-----+-----+-----+-----+ 343 | | | ? | ? | ? | ? | //for i = 0 | |-------| +-----+-----+-----+-----+ | 201 | +-----------▲ +--------+ 502 506 510 514 | | +-----+-----+-----+-----+ 347 | | | ? | ? | ? | ? | //for i = 1 | 502 |-------| +-----+-----+-----+-----+ +--------+ +-----------▲ data1.a_collision[0] = 201 data1.a_collision[1] = 502 

在图片I中,假设HASH_TABLE_SIZE = 4并且int = 4字节的大小,请注意地址的值a

现在这些是正确的分配步骤。

释放内存:

其他然后分配你的释放步骤是错误的!

记住,一旦你在某个指针上调用free,就无法访​​问该指针(也可以通过其他指针访问内存),这样做会调用未定义的行为 - 这是一个非法的内存指令,可以在运行时检测到可能导致的分段错误以及检测到的堆腐败。

正确的释放步骤与下面的分配相反:

 for(int i = 0; i < 2; i++) free(data1.a_collision[i]); // free memory for each rows free(data1.a_collision); //free for address of rows. 

更进一步,这是为二维数组分配内存的一种方法,就像你试图做的那样。 但是有更好的方法可以连续为完整的2D数组分配内存,你应该阅读“在函数C中分配内存2d数组” (对于这个链接的答案,我还给出了如何为3D数组分配内存的链接)。

这是一个开始:

你的“外部数组”有两个整数的空间,而不是两个整数的指针。

HASH_TABLE_SIZE是否等于2? 否则,您的第一个for循环将写入您刚分配的数组之外。

有几个问题:

  1. 第一次分配不正确,你应该分配一个(int *)数组:

      #define DIM_I 2 #define DIM_J HASH_TABLE_SIZE data1.a_collision = (int**)malloc(sizeof(int*)*DIM_I); 
  2. 第二个不再正确:

      for (int i = 0; i < DIM_I; i++) data1.a_collision[i] = (int*)malloc(sizeof(int)*DIM_J); 
  3. 当你释放内存时,你必须在LastInFirstOut命令中释放:

      for (int i = 0; i < DIM_I; i++) free(data1.a_collision[i]); free(data1.a_collision);