[英]Seg fault when using structure pointers to access struct members in C
我的程序有什么問題,當我嘗試打印值時出現段錯誤。
我的目標是在sample_function中分配一些值。
在主要功能中,我想將結構復制到另一個結構。
#include<stdio.h>
#include<string.h>
typedef struct
{
char *name;
char *class;
char *rollno;
} test;
test *
sample_function ()
{
test *abc;
abc = (test *)malloc(sizeof(test));
strcpy(abc->name,"Microsoft");
abc->class = "MD5";
abc->rollno = "12345";
printf("%s %s %s\n",abc->name,abc->class,abc->rollno);
return abc;
}
int main(){
test *digest_abc = NULL;
test *abc = NULL;
abc = sample_function();
digest_abc = abc;
printf(" %s %s %s \n",digest_abc->name,digest_abc->class,digest_abc->rollno);
return 1;
}
指針一直是我的噩夢,但我從未理解。
test * sample_function ()
{
test *abc;
strcpy(abc->name,"Surya");
您認為abc
在這里指向什么? 答案是,它並沒有真正指向任何東西。 您需要將其初始化為某種東西,在這種情況下,這意味着分配一些內存。
因此,讓我們解決第一個問題:
test * sample_function ()
{
test *abc = malloc(sizeof(*abc));
strcpy(abc->name,"Surya");
現在, abc
指向某個東西,我們可以在其中存儲東西!
但是... abc->name
也是一個指針,您認為這指向什么? 同樣,它實際上並沒有指向任何內容,並且您當然不能假設它指向可以存儲字符串的位置。
因此,讓我們解決第二個問題:
test * sample_function ()
{
test *abc = malloc(sizeof(*abc));
abc->name = strdup("Surya");
/* ... the rest is ok ... */
return abc;
}
現在,有最后一個問題:您永遠不會釋放剛剛分配的內存(這在這里可能不是問題,但這可能是全尺寸程序中的錯誤)。
因此,在main的最后,您應該有類似
free(abc->name);
free(abc);
return 1;
}
最后一個問題是設計問題:結構中有三個指針,只有一個約定可以幫助您記住哪個是動態分配的(必須釋放),哪個指向字符串文字( 必須不能釋放)。
只要在所有地方都遵循此約定,就可以了。 一旦動態分配class
或rollno
,就會發生內存泄漏。 只要將name
指向字符串文字,就會造成崩潰和/或堆損壞。
正如japreiss在評論中指出的那樣, 執行約定的一種好方法是編寫專用函數,例如:
void initialize_test(test *obj, const char *name, char *class, char *rollno) {
obj->name = strdup(name);
...
}
void destroy_test(test *obj) {
free(obj->name);
}
test *malloc_test(const char *name, ...) {
test *obj = malloc(sizeof(*obj));
initialize_test(obj, name, ...);
return test;
}
void free_test(test *obj) {
destroy_test(obj);
free(obj);
}
在函數sample_function
,返回指向abc
的指針。 由於激活記錄的組織方式,您無法在C中執行此操作。
激活記錄是一種數據結構,其中包含有關函數調用,參數,返回地址,局部變量地址等的所有相關信息。
當您調用一個函數時,新的激活記錄將被推入堆棧,它看起來可能像這樣。
// Record for some function f(a, b)
| local variable 1 | <- stack pointer (abc in your case)
| local variable 2 |
| old stack pointer | <- base pointer
| return address |
| parameter 1 |
| parameter 2 |
---------------------
| caller activation |
| record |
從函數返回時,該激活記錄也會從堆棧中彈出 ,但是如果返回的是舊記錄中的變量的地址,會發生什么呢?
// popped record
| local variable 1 | <- address of abc #
| local variable 2 | #
| old stack pointer | # Unallocated memory, any new function
| return address | # call could overwrite this
| parameter 1 | #
| parameter 2 | #
--------------------- <- stack pointer
| caller activation |
| record |
現在,您嘗試使用abc,並且程序正確崩潰,因為它會看到您正在訪問未分配的內存區域。
您也有分配方面的問題,但是其他答案已經涵蓋了這一點。
在sample_function
您將abc
聲明為指向test
結構的指針,但從未對其進行初始化。 它只是指向某個地方的雜草。 然后嘗試取消引用它以存儲值-BOOM。
您的程序根本不需要任何指針。 可以在C中按值傳遞結構。
如果您確實想保持與現在相似的接口,則必須添加一些動態分配( malloc
/ free
調用),以確保結構已實際分配並且指針實際指向它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.