简体   繁体   English

为什么初始化结构时出现段错误?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM