我的程序出了什么问题,当我尝试打印值时,我遇到了seg错误。
我的目标是在sample_function中分配一些值。
并且在main函数中我想将结构复制到另一个结构。
#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;
}
指针对我来说一直是个噩梦,我从来不理解它。
答案 0 :(得分:5)
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;
}
最后一个问题是设计问题:你的结构中有三个指针,只有约定可以帮助你记住哪个是动态分配的(并且必须被释放),哪个指向字符串文字(并且必须不< / em>被释放)。
这很好,只要遵循此约定无处不在。只要您动态分配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);
}
答案 1 :(得分:1)
在函数sample_function
中,返回指向abc
的指针。由于 Activation Records 的组织方式,您无法在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并且您的程序正确崩溃,因为它看到您正在访问未分配的内存区域。
您也遇到分配问题,但其他答案已经涵盖了这一点。
答案 2 :(得分:0)
在sample_function
中,您将abc
声明为指向test
结构的指针,但您永远不会对其进行初始化。它只是指向某处的杂草。然后你尝试取消引用它来存储值 - BOOM。
你的程序根本不需要任何指针;结构可以通过C中的值传递。
如果您确实希望保留与现有类似的接口,则必须添加一些动态分配(malloc
/ free
调用)以确保实际分配您的结构并且你的指针实际指向它们。