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

C 返回指向结构的指针后出现分段错误,c,struct,return,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 vo

有一个从文件读取并返回结构的程序

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)如何修复此错误?

您返回的是指向函数末尾超出范围的变量的指针

  Ionogram ionogramObj;
  return &ionogramObj;
这是C语言中未定义的行为


另一种方法是,
malloc
在函数中为您的结构指定内存,并返回指向该内存的指针。不要忘记在某个点释放指针。

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

两种可能的解决办法:

  • 实际返回一个结构,按值返回,而不是指针
  • 使用
    malloc
    为结构分配内存,并返回指向此动态分配内存的指针

  • 方法一适用于较小的结构,如您的结构,但对于较大的结构来说效率较低,因为必须复制整个结构。(虽然它是浅拷贝,但不是深拷贝。因此,如果结构中有指针,则只复制指针,而不是指针指向的对象。)

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

    访问无效地址(指针)调用。分割错误是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以避免内存泄漏。一旦使用完返回值,就可以在调用者中使用返回的指针(
    main()
    )调用
    free()

    @BlagovestBuyukliev True,但它还有其他缺点(例如可重入性和线程安全性)@BlagovestBuyukliev:这种建议有点像告诉学习驾驶的人用左脚刹车。当然,如果你渴望F1,这是一项很有用的技能,但首先不要让事情复杂化。第三个也是最好的行业事实上的标准解决方案:在调用者中分配结构并传递指向它的指针。谢谢!第一个答案是为我工作!我认为,第二种方法并不适合我的情况,因为我不知道在函数read返回之前需要分配多少字节。也许我错了。