搜索了一个小时。我想我最好在这里发布这个问题。
我简化了代码。段错误在函数initMyStruct
中。
#include "stdlib.h"
typedef struct {
int * arr1;
int * arr2;
} myStruct;
void allocMyStruct (myStruct * a, int num) {
a = malloc(sizeof(myStruct));
a->arr1 = malloc(10*sizeof(int));
a->arr2 = malloc(10*num*sizeof(int));
}
void initMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) a->arr1[i] = 0;
for (i = 0; i < 10*num; i++) a->arr2[i] = -1;
}
void freeMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) free(a->arr1);
for (i = 0; i < 10*num; i++) free(a->arr2);
free(a);
}
int main (void) {
int num = 3;
myStruct * a;
allocMyStruct (a, num);
initMyStruct (a, num);
freeMyStruct (a, num);
return 1;
}
答案 0 :(得分:5)
因为你没有保持指向新分配的内存的指针,而是使用未初始化的指针并获得未定义的行为。
您将a
变量传递给allocMyStruct()
,但该调用(与所有其他人一样)按值,因此在函数内部分配给它的新值确实如此不会影响a
中main()
的值。
更改它以便allocMyStruct()
返回新指针值,或者获取指针指针。我更喜欢前者,它更干净,使用函数返回值通常会产生更好的代码:
myStruct * allocMyStruct(int num)
{
myStruct *p;
if((p = malloc(sizeof *p +
10 * sizeof *p->arr1 +
10 * num * sizeof *p->arr2)) != NULL)
{
p->arr1 = (int *) (p + 1);
p->arr2 = p->arr1 + 10;
}
return p;
}
上面的代码还简化了内存分配,在一个大的malloc()
调用中完成所有操作,然后将其“切片”为您实际需要的三个部分。
如果arr1
的大小总是10,那么动态分配是没有意义的,它应该只是结构声明中的int arr1[10];
。
答案 1 :(得分:2)
a
未初始化时使用,请更改为:
myStruct * allocMyStruct (int num) {
myStruct *a;
a = malloc(sizeof(myStruct));
a->arr1 = malloc(10*sizeof(int));
a->arr2 = malloc(10*num*sizeof(int));
return a;
}
myStruct * a = allocMyStruct(num);
此外,您无需循环使用自由功能
void freeMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) free(a->arr1);
for (i = 0; i < 10*num; i++) free(a->arr2);
free(a);
}
必须
void freeMyStruct (myStruct * a) {
free(a->arr1);
free(a->arr2);
free(a);
}
答案 2 :(得分:1)
当您调用void allocMyStruct (myStruct * a, int num)
时,a
指针将作为值传递,而a
参数是指针来自main
的本地副本,在您更改之后您的三个函数中的任何一个中的本地a
,main
中都不会更改。
为此,您必须使用双指针作为函数参数,因此这些函数将获取指针的地址,以便他们可以修改它。
#include "stdlib.h"
typedef struct {
int * arr1;
int * arr2;
} myStruct;
void allocMyStruct (myStruct ** a, int num) {
*a = malloc(sizeof(myStruct));
(*a)->arr1 = malloc(10*sizeof(int));
(*a)->arr2 = malloc(10*num*sizeof(int));
}
void initMyStruct (myStruct ** a, int num) {
int i;
for (i = 0; i < 10; i++) (*a)->arr1[i] = 0;
for (i = 0; i < 10*num; i++) (*a)->arr2[i] = -1;
}
void freeMyStruct (myStruct ** a, int num) {
free((*a)->arr1);
free((*a)->arr2);
free(*a);
*a = NULL;
}
int main (void) {
int num = 3;
myStruct * a;
allocMyStruct (&a, num);
initMyStruct (&a, num);
freeMyStruct (&a, num);
return 1;
}
编辑:Alter Mann关于多次释放相同地址是对的,在linux上你会因双重释放而立即崩溃。他有一个更简单的解决方案。