使用结构指针访问C中的struct成员时出现Seg错误

时间:2013-06-14 15:20:57

标签: c pointers structure

我的程序出了什么问题,当我尝试打印值时,我遇到了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;

}

指针对我来说一直是个噩梦,我从来不理解它。

3 个答案:

答案 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>被释放)。

这很好,只要遵循此约定无处不在。只要您动态分配classrollno,就会发生内存泄漏。只要将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调用)以确保实际分配您的结构并且你的指针实际指向它们。