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返回之前需要分配多少字节。也许我错了。