2

我的程序出了什么问题,当我尝试打印值时出现段错误。

我的目标是在 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;

}

指针对我来说一直是一个噩梦,我一直不明白。

4

3 回答 3

7
test * sample_function ()
{
    test *abc;

    strcpy(abc->name,"Surya");

What do you think abc points to, here? The answer is, it doesn't really point to anything. You need to initialize it to something, which in this case means allocating some memory.

So, let's fix that first issue:

test * sample_function ()
{
    test *abc = malloc(sizeof(*abc));

    strcpy(abc->name,"Surya");

Now, abc points to something, and we can store stuff in there!

But ... abc->name is a pointer too, and what do you think that points to? Again, it doesn't really point to anything, and you certainly can't assume it points somewhere you can store your string.

So, let's fix your second issue:

test * sample_function ()
{
    test *abc = malloc(sizeof(*abc));

    abc->name = strdup("Surya");
    /* ... the rest is ok ... */
    return abc;
}

Now, there's one last issue: you never release the memory you just allocated (this probably isn't an issue here, but it'd be a bug in a full-sized program).

So, at the end of main, you should have something like

    free(abc->name);
    free(abc);
    return 1;
}

The final issue is a design one: you have three pointers in your structure, and only convention to help you remember which is dynamically allocated (and must be freed) and which point to string literals (and must not be freed).

That's fine, so long as this convention is followed everywhere. As soon as you dynamically allocate class or rollno, you have a memory leak. As soon as you point name at a string literal, you'll have a crash and/or heap damage.

As japreiss points out in a comment, a good way to enforce your convention is to write dedicated functions, like:

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);
}
于 2013-06-14T15:23:10.207 回答
1

在您的函数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 并且您的程序正确地崩溃了,因为它看到您正在访问一个未分配的内存区域。

您也有分配问题,但其他答案已经涵盖了这一点。

于 2013-06-14T15:38:39.847 回答
0

In sample_function you declare abc as a pointer to a test structure, but you never initialize it. It's just pointing off into the weeds somewhere. Then you try to dereference it to store values - BOOM.

Your program doesn't need any pointers at all; structures can be passed by value in C.

If you do want to keep similar interfaces to what you have now, you're going to have to add some dynamic allocations (malloc/free calls) to make sure your structures are actually allocated and that your pointers actually point to them.

于 2013-06-14T15:22:40.520 回答