在c中的2d数组中释放2d数组时遇到的问题
我的程序的简要概述:它包含大约500组初始参数。然后,它将这500个数据分成50个“块”,这样它就可以计算出50个数据并将结果写入文件,然后继续下一个50个“块”,等等。这是一个检查点系统。无论如何,对于每个“块”,都会创建一个名为在c中的2d数组中释放2d数组时遇到的问题,c,multidimensional-array,memory-management,heap-memory,free,C,Multidimensional Array,Memory Management,Heap Memory,Free,我的程序的简要概述:它包含大约500组初始参数。然后,它将这500个数据分成50个“块”,这样它就可以计算出50个数据并将结果写入文件,然后继续下一个50个“块”,等等。这是一个检查点系统。无论如何,对于每个“块”,都会创建一个名为calc\u result的结构数组来保存50个结果。每个calc_结果都包含一个名称、一个索引和一个用于实际结果的2d字符数组。然后工作完成并写入文件,当前的calc\u结果数组被释放。以下是基本程序: typedef struct { char* name
calc\u result
的结构数组来保存50个结果。每个calc_结果都包含一个名称、一个索引和一个用于实际结果的2d字符数组。然后工作完成并写入文件,当前的calc\u结果
数组被释放。以下是基本程序:
typedef struct
{
char* name;
int index;
char** finals;
} calc_results;
int main(int argc, char** argv)
{
//read in sets of initial parameters
int numChunks = 10;
int calcsPerChunk = 50;
for(int i = 0; i < numChunks; i++)
{
calc_result** results = malloc(sizeof(calc_result*)*calcsPerChunk);
for(int j = 0; j < calcsPerChunk; j++)
{
results[j] = malloc(sizeof(calc_result));
results[j]->name = "blah";
results[j]->index = j;
results[j]->finals = malloc(sizeof(char*) * 12); //12 final results
for(int k = 0; k < 12; k++)
{
results[j]->finals[k] = malloc(70); //max string size is 70
}
}
//DO ACTUAL WORK
//WRITE RESULTS TO FILE
//FREE STUFF:
for(int a = 0; a < calcsPerChunk; a++)
{
for(int b = 0; b < 12; b++)
{
free(results[a]->finals[b]);
}
free(results[a]->name);
free(results[a]->finals);
free(results[a]);
}
free(results);
}
}
typedef结构
{
字符*名称;
整数指数;
半决赛;
}计算结果;
int main(int argc,字符**argv)
{
//读入初始参数集
int numChunks=10;
int calcsPerChunk=50;
for(int i=0;iname=“blah”;
结果[j]->指数=j;
结果[j]->finals=malloc(sizeof(char*)*12);//12最终结果
对于(int k=0;k<12;k++)
{
结果[j]->final[k]=malloc(70);//最大字符串大小为70
}
}
//实际工作
//将结果写入文件
//免费物品:
对于(int a=0;a决赛[b]);
}
免费(结果[a]->名称);
免费(结果[a]->决赛);
免费(结果[a]);
}
免费(结果);
}
}
我在释放结果方面遇到了麻烦。该程序运行10个“块”中的7个,并释放1个calcsPerChunk
(即i=8
,a=1
和b=0
),然后抛出一个指向free(results[a]->final[b])
行的错误。该错误无效:“Program.exe”已触发断点。“我不确定我做错了什么,有人能帮忙吗?注意:您的代码中没有数组,因此您的问题标题用词不当。您正在为指针类型分配指针,首先为每个对象分配指针,然后为每个对象分配一个存储块,然后为指针分配每个存储块的起始地址。(规则:指针不是数组,数组也不是指针——尽管在访问时,数组会根据规则转换为指向第一个元素的指针)
您唯一的问题是试图释放(results[a]->name)代码>未分配,然后您无法验证每个分配的返回值。除此之外,你们非常亲密。你知道你需要什么来释放
以及在中释放的顺序(results[a]->name)代码>看起来更像是一个“…duh…”
错误,而不是理解上的任何错误
您还可以通过使用取消引用的指针来调整每个分配的类型大小,而不是尝试调用X-type
forsizeof(X-type)
,这在某些情况下很容易出错。例如,而不是:
calc_result** results = malloc(sizeof(calc_result*)*calcsPerChunk);
您可以使用sizeof*results
(取消引用的指针)设置每个对象的大小,例如:
calc_results **results = malloc (sizeof *results * calcsPerChunk);
注意:的'*'
或'**'
通常与指针一起使用,而不是与类型一起使用。为什么?,语义和使指针显式。例如:
calc_results* a, b, c;
当然不会声明指向计算结果的三指针。相反,它声明指向计算结果a
和两个结构计算结果b,c
的指针。确保“*”
位于指针上可以清楚地表明这一点,例如
calc_results *a, b, c;
(就法律语法而言,这没有什么区别,编译器可以毫无问题地解析它——问题往往发生在人的方面)
确认您方法的快速示例
对于测试,您不需要:
int numChunks = 10;
int calcsPerChunk = 50;
(3
和5
(或比1
更多的内容)就可以了)
结合一个简短的示例,通过使用取消引用的指针验证每个分配并调整每个分配的大小(并为每个级别吐出输出,只是为了好玩),您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *name;
int index;
char **finals;
} calc_results;
int main(void)
{
int numChunks = 3;
int calcsPerChunk = 5;
for(int i = 0; i < numChunks; i++) {
calc_results **results = malloc (sizeof *results * calcsPerChunk);
if (!results) {
perror ("malloc-results");
return 1;
}
for(int j = 0; j < calcsPerChunk; j++)
{
if (!(results[j] = malloc (sizeof *results[j]))) {
perror ("malloc-results[j]");
return 1;
}
results[j]->name = "blah";
results[j]->index = j;
if (!(results[j]->finals=malloc(sizeof *results[j]->finals*12))) {
perror ("malloc-results[j]->finals");
return 1;
}
for(int k = 0; k < 12; k++) {
if (!(results[j]->finals[k] = malloc(70))) {
perror ("malloc-results[j]->finals[k]");
return 1;
}
sprintf (results[j]->finals[k], "grade %d", k+1);
}
}
/* DO ACTUAL WORK */
/* output & free stuff */
printf ("results[%2d]\n", i);
for (int a = 0; a < calcsPerChunk; a++) {
printf (" %s %2d\n", results[a]->name, results[a]->index);
for (int b = 0; b < 12; b++) {
printf (" %s\n", results[a]->finals[b]);
free (results[a]->finals[b]);
}
// free(results[a]->name);
free(results[a]->finals);
free(results[a]);
}
free(results);
}
}
始终确认已释放所有已分配的内存,并且没有内存错误
仔细检查一下,如果你还有其他问题,请告诉我。你真的非常接近,我怀疑你实际上是在实际代码中分配name
,所以你的代码很可能已经工作了。你没有检查内存分配malloc()
是否成功。免费(结果[a]->期末[b])代码>原因错误。代码越来越长,所以我去掉了检查和内存集。分配内存时没有报告错误。其中空闲(results[a]->name)代码>已分配?(这是一个大问题)@esmaele-results[j]>final[k]=malloc(70)
很好sizeof(char)
始终是1
。谢谢您的帮助。你说得对-我在代码中对名称进行了malloc'ed,但忘记将其放在代码示例中。你关于内存错误测试的评论让我思考,我确实在这个calc_results
allocation code之前使用的单独函数中发现了内存泄漏。它是固定的,现在calc\u结果stuff工作了!不客气。很明显你明白你在做什么。深度嵌套分配中唯一的挑战是戴上“会计帽”,点上所有“I”
并交叉所有“T”
,以确保每个分配都以正确的顺序与free()
配对。不,我的
$ valgrind ./bin/free_nested_struct
==13663== Memcheck, a memory error detector
==13663== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==13663== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==13663== Command: ./bin/free_nested_struct
==13663==
results[ 0]
blah 0
grade 1
grade 2
grade 3
grade 4
grade 5
grade 6
...
<snip>
==13663==
==13663== HEAP SUMMARY:
==13663== in use at exit: 0 bytes in 0 blocks
==13663== total heap usage: 213 allocs, 213 frees, 14,520 bytes allocated
==13663==
==13663== All heap blocks were freed -- no leaks are possible
==13663==
==13663== For counts of detected and suppressed errors, rerun with: -v
==13663== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)