C 为什么在初始化结构时出现SEGFULT?

C 为什么在初始化结构时出现SEGFULT?,c,struct,segmentation-fault,malloc,C,Struct,Segmentation Fault,Malloc,搜索了一个小时。我想我最好把问题贴在这里 我简化了代码。segfault位于函数initMyStruct中 #include "stdlib.h" typedef struct { int * arr1; int * arr2; } myStruct; void allocMyStruct (myStruct * a, int num) { a = malloc(sizeof(myStruct)); a->arr1 = m

搜索了一个小时。我想我最好把问题贴在这里

我简化了代码。segfault位于函数
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;
}
#包括“stdlib.h”
类型定义结构{
int*arr1;
int*arr2;
}我的结构;
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;
对于(i=0;i<10;i++)a->arr1[i]=0;
对于(i=0;i<10*num;i++)a->arr2[i]=-1;
}
void freemystract(myStruct*a,int num){
int i;
对于(i=0;i<10;i++)自由(a->arr1);
对于(i=0;i<10*num;i++)空闲(a->arr2);
免费(a);
}
内部主(空){
int num=3;
myStruct*a;
allocMyStruct(a,num);
initMyStruct(a,num);
freeMyStruct(a,num);
返回1;
}

因为您没有保留指向新分配内存的指针,而是使用未初始化的指针并获得未定义的行为

您将
a
变量传递到
allocMyStruct()
,但该调用(与所有其他调用一样)是按值进行的,因此在函数内部分配给它的新值不会影响
main()
a
的值

更改它,以便
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,那么动态分配它就没有意义了,它应该是
intarr1[10]
您将
a
变量传递到
allocMyStruct()
,但该调用(与所有其他调用一样)是按值进行的,因此在函数内部分配给它的新值不会影响
main()
a
的值

更改它,以便
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,那么动态分配它就没有意义了,它应该是
intarr1[10]

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);
另外,不需要在free函数中循环

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);
}

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);
另外,不需要在free函数中循环

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 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;
}
#包括“stdlib.h”
类型定义结构{
int*arr1;
int*arr2;
}我的结构;
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;
对于(i=0;i<10;i++)(*a)->arr1[i]=0;
对于(i=0;i<10*num;i++)(*a)->arr2[i]=-1;
}
void freemystract(myStruct**a,int num){
自由((*a)->arr1);
自由((*a)->arr2);
免费(*a);
*a=零;
}
内部主(空){
int num=3;
myStruct*a;
allocMyStruct(&a,num);
initMyStruct(&a,num);
freeMyStruct(&a,num);
返回1;
}

编辑:AlterMann关于同一地址的多次释放是正确的,在linux上,双重释放会导致即时崩溃。他有一个更简单的解决方案。

当您调用
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;
}
#包括“stdlib.h”
类型定义结构{
int*arr1;
int*arr2;
}我的结构;
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;
对于(i=0;i<10;i++)(*a)->arr1[i]=0;
对于(i=0;i<10*num;i++)(*a)->arr2[i]=-1;
}
void freemystract(myStruct**a,int num){
自由((*a)->arr1);
自由((*a)->arr2);
免费(*a);
*a=零;
}
内部主(空){
int num=3;
myStruct*a;
allocMyStruct(&a,num);
initMyStruct(&a,num);
freeMyStruct(&a,num);
返回1;
}
编辑:AlterMann关于在l上多次释放同一地址是正确的