我在此结构内有一个动态的2D数组:
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;
}
这就是我释放2D数组的方式:
void freeMatrix(int **matrix, int rows)
{
int i;
for (i = 0; i < rows; i++){
free(matrix[i]);
}
free(matrix);
matrix = NULL;
}
我看到的奇怪的behvior是,当我编译并运行程序时,一切看起来都还好。但是,当我将stdout送到txt文件时,我会遇到SEG错误。但是,如果我评论包含" freematrix"调用的循环,则不会发生SEG故障。我在做什么错?
我在免费代码中看不到任何问题,除了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);
在Sidenote上:初始化您的astruct
array
。
mystruct astruct[100] = {};
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);
您分配了一个ASCUCT,但免费100个;如果99个额外的额外的任何一个都不为空,那将崩溃,当您进行重定向时,这可能会发生。(由于Ascruct在堆栈上,它将包含那里留在那里的所有内容。)
其他问题:
您使用的是数字文字而不是明显常数...定义数字和numcols并始终如一地使用它们。
摆脱第一个dectarematrix的参数...您传递一个值,但永远不会使用它。
在freematrix中,
matrix = NULL;
什么也不做。通过优化开启,编译器甚至不会生成任何代码。
if (mymatrix==NULL)
printf("Error allocating memory!n");
您应该在错误时退出(1),否则您的程序将崩溃,甚至可能不会看到错误消息,因为a)Stdout被缓冲,并且b)您将其重定向到文件。这也是将错误消息写给stderr而不是Stdout的原因。
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
您没有传递指针的地址。它只是将内存中的值传递到不符合不关键的函数。
和您唯一的初始化结构的第一个变量,但是当您试图释放内存时,您正在未分配内存(尚未分配)(astruct [1]等,依此类推,直到100)。
当您使用Malloc时,它实际上比您指定的要多得多。额外的内存用于存储信息,例如块的大小,以及指向下一个免费/二手块的链接,有时是一些 guard data ,可以帮助系统检测是否在过去的末尾写入分配的块。
如果您通过其他地址,它将访问包含垃圾的内存,因此其行为不确定(但最常导致崩溃)
索引并计数一个未签名的整数类型就足够了。size_t
是这种选择的类型,因为它保证足够大,可以在目标计算机上的每个字节/数组的元素解决/索引。
struct mystruct
{
size_t mySize;
int ** networkRep;
};
始终正确初始化变量:
struct myStruct astruct[100] = {0};
分配器的几个问题:
- 让它有机会返回特定的错误代码。这通常是通过使用返回的函数为so的函数来完成的。
- 使用
size_t
进行计数器,指示和大小("行","列")(有关为什么请参见上文)。 - 进行适当的错误检查。
- 在工作期间发生错误时清理。
- 请勿施放
malloc()
返回的值,因为在C中,不需要,不推荐 - 使用
perror()
来记录错误,因为它从OS中获得最大的AS aS Possibe。
可以做到的:
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;
}
De-Olocator的两个问题:
- 马克(Mark
- 在采取行动之前对输入进行验证。
可以做到的:
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);
}
}