[英]Why I get segfault when initializing the struct?
Searched around for one hour. 搜索了一个小时。 I guess I'd better post the question here. 我想我最好在这里发布问题。
I simplify the code. 我简化了代码。 The segfault is in the function initMyStruct
. 段错误位于函数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;
}
Because you're not keeping the pointer to the newly allocated memory, instead you use an uninitialized pointer and getting undefined behavior. 因为您没有保留指向新分配的内存的指针,所以您使用了未初始化的指针并获得了未定义的行为。
You pass the a
variable into allocMyStruct()
, but that call is (like all others) by value , so the new value being assigned to it inside the function does not affect the value of a
in main()
. 您将a
变量传递给allocMyStruct()
,但是该调用(与其他所有变量一样)是按值进行的 ,因此在函数内部分配给它的新值不会影响main()
中a
的值。
Change it so that allocMyStruct()
either returns the new pointer value, or takes a pointer to the pointer. 对其进行更改,以使allocMyStruct()
返回新的指针值,或获取指向该指针的指针。 I would prefer the former, it's cleaner and using function return values often leads to better code: 我更喜欢前者,它更干净,使用函数返回值通常可以产生更好的代码:
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;
}
The above code also streamlines the memory allocation, doing it all in one big malloc()
call which is then "sliced" into the three parts you actually need. 上面的代码还简化了内存分配,在一个大的malloc()
调用中完成了所有工作,然后将其“切片”为您实际需要的三个部分。
If the size of arr1
is always 10 by the way, there's no point in having it dynamically allocated, it should just be int arr1[10];
顺便说一下,如果arr1
的大小始终为10,则没有必要动态分配它,它应该只是int arr1[10];
in the struct declaration. 在结构声明中。
a
is used uninitialized, change to: 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);
Also, there is no need to loop in your free function 此外,也不需要循环您的免费功能
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);
}
Must be 一定是
void freeMyStruct (myStruct * a) {
free(a->arr1);
free(a->arr2);
free(a);
}
When you call void allocMyStruct (myStruct * a, int num)
the a
pointer will be passed as a value and the a
parameter is a local copy of your pointer from main
, after you change the local a
in any of your three functions, it will not change in main
. 当你调用void allocMyStruct (myStruct * a, int num)
的a
指针将作为值传递和a
参数是你的指针从一个本地副本main
,你改变了当地后, a
在你的任何三个功能,它main
不会改变。
For this you have to use double pointer as a function argument, so those functions will get an address of a pointer so they can modify it. 为此,您必须使用双指针作为函数参数,因此这些函数将获得指针的地址,以便他们可以对其进行修改。
#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;
}
EDIT: Alter Mann is right about multiple freeing of the same address, on linux you would get instant crash for double freeing. 编辑:Alter Mann对同一地址的多个释放是正确的,在Linux上,您将立即因两次释放而崩溃。 And he has a simpler solution. 而且他有一个更简单的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.