返回指向结构的指针后出现分段错误

时间:2015-08-17 10:44:16

标签: c struct return

有从文件中读取的程序并返回结构。

struct ion_bin
{
    int freq;
    long height;
    int amplitude;
};

//Dynamic auto allocating array
typedef struct {
  struct ion_bin *array;
  size_t used;
  size_t size;
} Ionogram;

void freeArray(Ionogram *a); //free memory
void insertArray(Ionogram *a, struct ion_bin element); //realloc memory
void initArray(Ionogram *a, size_t initialSize); //malloc memory

Ionogram* read(int argn, char* argv[])
{
    FILE* stream;
    Ionogram ionogramObj;

    //fill ionogram from file by initArray and insertArray  
    //.....

    return &ionogramObj;
}

int main(int argn, char* argv[])
{
    Ionogram* r = read(argn, argv);

    fprintf(stderr,"Array size: %d Used %d\n",r->size, r->used); //SEGMENTATION FAULT ERROR
    //int second = (*(r->array + 2)).amplitude; //YET SEGMENTATION FAULT ERROR TOO

    //fprintf(stderr, "%d", second);
    return 0;
}

此程序编译成功,但在运行时和调试中通过尝试获取返回结构的字段(在main方法中)触发分段错误错误(SIGSEGV)如何修复此错误?

3 个答案:

答案 0 :(得分:4)

你犯了一个初学者错误,并返回一个指向局部变量的指针。你必须记住,一旦函数返回,局部变量就会超出范围,并且指向它的指针将变为无效。取消引用此无效指针会导致未定义的行为

两种可能的解决方案:

  1. 实际上按值返回结构,而不是指针。
  2. 使用malloc为结构分配内存,并返回指向此动态分配内存的指针。
  3. 方法一适用于较小的结构,如你的,但对于较大的结构效率低,因为必须复制整个结构。 (虽然这是一个副本,但不是深层副本。所以如果你在结构中有指针,那么只复制指针而不是它们所指向的指针。)

答案 1 :(得分:2)

您正在返回一个指向函数末尾超出范围的变量的指针。

  Ionogram ionogramObj;
  return &ionogramObj;

C中的未定义行为。

作为替代,malloc函数中结构的内存并返回指向该结构的指针。在某些时候别忘了free指针。

答案 2 :(得分:1)

在您的代码中,ionogramObj变量是函数read()的本地变量。一旦函数完成执行,就不存在ionogramObj,因此,实际上返回的地址在调用者(main())中变为无效。

访问无效地址(指针)会调用undefined behaviour。分割错误是UB的副作用之一。

为避免这种情况,您需要返回一个寿命大于被调用函数的地址。借助指针和动态内存分配,您可以实现此目的。

查看伪代码

Ionogram* read(int argn, char* argv[])
{
    FILE* stream = NULL; 
    Ionogram *ionogramObj = NULL;                 //take a pointer

    ionogramObj = malloc(sizeof(*ionogramObj));   //allocate memory dynamically

    if (!ionogramObj)                             //don't forget to check for success
      //some error message, return or exit, maybe?
    else
       //do normal operation
    //fill ionogram from file by initArray and insertArray  
    //.....

    return ionogramObj;                           //return the pointer
}

此外,动态分配的内存需要free() d以避免内存泄漏。使用返回值完成后,可以使用调用者(free())中返回的指针调用main()