我在这个结构中有一个动态的二维数组:
struct mystruct{
int mySize;
int **networkRep;
};
在我的代码块中,我按如下方式使用它:
struct myStruct astruct[100];
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
// do stuff...
int i;
for(i=0; i<100; i++)
freeMatrix(astruct[i].networkRep, 200);
这是我声明2d数组的方式:
int** declareMatrix(int **mymatrix, int rows, int columns)
{
mymatrix = (int**) malloc(rows*sizeof(int*));
if (mymatrix==NULL)
printf("Error allocating memory!\n");
int i,j;
for (i = 0; i < rows; i++)
mymatrix[i] = (int*) malloc(columns*sizeof(int));
for(i=0; i<rows; i++){
for(j=0; j<columns; j++){
mymatrix[i][j] = 0;
}
}
return mymatrix;
}
这就是我释放二维数组的方式:
void freeMatrix(int **matrix, int rows)
{
int i;
for (i = 0; i < rows; i++){
free(matrix[i]);
}
free(matrix);
matrix = NULL;
}
我所看到的奇怪的行为是,当我编译并运行我的程序时,一切看起来都不错。但是当我将stdout传输到txt文件时,我遇到了一个seg错误。但是,如果我注释掉包含&#34; freeMatrix&#34;的循环,则不会发生seg错误。呼叫。我做错了什么?
答案 0 :(得分:1)
我发现免费代码没有任何问题,除了freeMatrix
被调用100
次,而您的分配只是1
。
所以,你要么分配如下:
for(int i=0; i<100; i++) //Notice looping over 100 elements.
astruct[i].networkRep = declareMatrix(astruct[i].networkRep, 200, 200);
或者,只为您在原始代码中分配的第0个元素免费。
freeMatrix(astruct[0].networkRep, 200);
旁注:初始化astruct
array
。
mystruct astruct[100] = {};
答案 1 :(得分:1)
struct myStruct astruct[100];
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
// do stuff...
int i;
for(i=0; i<100; i++)
freeMatrix(astruct[i].networkRep, 200);
你分配了一个astruct,但释放了100个;如果任何99个额外的不是NULL,那么会崩溃,这可能在你进行重定向时发生。 (由于astruct在堆栈中,它将包含留在那里的任何内容。)
其他问题:
您使用的是数字文字而不是显式常量...定义NUMROWS和NUMCOLS并一致地使用它们。
摆脱declareMatrix的第一个参数......你传递一个值但从不使用它。
在freeMatrix中,
matrix = NULL;
什么都不做。启用优化后,编译器甚至不会生成任何代码。
if (mymatrix==NULL)
printf("Error allocating memory!\n");
您应该在出错时退出(1),否则您的程序将崩溃,您甚至可能看不到错误消息,因为a)stdout被缓冲并且b)您将其重定向到文件。这也是将错误消息写入stderr而不是stdout的原因。
答案 2 :(得分:0)
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
你没有传递指针的地址。它只是将内存中的值传递给不需要的函数。
你唯一初始化struct的第一个变量,但是当你试图释放内存时,你正在分配尚未分配的内存(astruct [1],依此类推,直到100)。
当您使用malloc时,它实际上分配的内存比您指定的多一点。额外内存用于存储诸如块大小之类的信息,以及指向下一个空闲/已使用块的链接,有时还包含一些保护数据,这有助于系统检测您是否写过了结束分配块。
如果传入不同的地址,它将访问包含垃圾的内存,因此其行为未定义(但最常见的是导致崩溃)
答案 3 :(得分:0)
索引和计数无符号整数类型就足够了。 size_t
是这种类型的选择,因为它保证足够大以处理/索引目标机器上内存/数组元素的每个字节。
struct mystruct
{
size_t mySize;
int ** networkRep;
};
始终正确初始化变量:
struct myStruct astruct[100] = {0};
分配器的几个问题:
size_t
作为计数器和指示和尺寸(“行”,“列”)(为什么请参见上文)。malloc()
, as in C it's not necessary, not recommended perror()
记录错误,因为它从操作系统中获得了最多关于可能的错误。可以这样做:
int declareMatrix(int *** pmymatrix, size_t rows, size_t columns)
{
int result = 0; /* Be optimistc. */
assert(NULL != pmatrix);
*pmymatrix = malloc(rows * sizeof(**pmymatrix));
if (NULL == *pmymatrix)
{
perror("malloc() failed");
result = -1;
goto lblExit;
}
{
size_t i, j;
for (i = 0; i < rows; i++)
{
(*pmymatrix)[i] = malloc(columns * sizeof(***pmymatrix));
if (NULL == (*pmymatrix)[i])
{
perror("malloc() failed");
freeMatrix(pmymatrix); /* Clean up. */
result = -1;
goto lblExit;
}
for(i = 0; i < rows; ++i)
{
for(j = 0; j < columns; ++j)
{
(*pmymatrix)[i][j] = 0;
}
}
}
}
lblExit:
return 0;
}
解除分配器的两个问题:
可以这样做:
void freeMatrix(int *** pmatrix, size_t rows)
{
if (NULL != pmatrix)
{
if (NULL != *pmatrix)
{
size_t i;
for (i = 0; i < rows; ++i)
{
free((*pmatrix)[i]);
}
}
free(*pmatrix);
*pmatrix = NULL;
}
}
然后使用这样的东西:
struct myStruct astruct[100] = {0};
...
int result = declareMatrix(&astruct[0].networkRep, 200, 200);
if (0 != result)
{
fprintf("declareMatrix() failed.\n");
}
else
{
// Note: Arriving here has only the 1st element of astruct initialised! */
// do stuff...
}
{
size_t i;
for(i = 0; i < 100; ++i)
{
freeMatrix(&astruct[i].networkRep, 200);
}
}