Malloc() 和 free() 阻止我在 C 中按值传递结构

Malloc() and free() stopping me from passing structs by value in C

我正在做一个项目,但我一直遇到分段错误,而且结构的值没有被传递。弄清楚为什么让我发疯。我已经尝试用更简单的程序找出问题,我想我已经找到了问题,但我不确定如何解决它。

问题是,当我 "malloc" 一个结构,然后按值传递时,值丢失了。稍后添加 "free" 会产生分段错误。我没有尝试访问 "malloc()" 之前或 "free()" 之后的值,所以我很困惑为什么会这样。

这是问题的简单模型:

#include <stdlib.h>
#include <stdio.h>

    struct structexample
    {
        int element;
    };

    void initStruct(struct structexample * teststruct, int * number)
    {
        teststruct = malloc(sizeof(struct structexample)); 
        teststruct->element = 10;
        printf("teststruct element is %d in initStruct\n", teststruct->element);
        *number = 5;
    }

    void printtest(struct structexample * teststruct, int * number)
    {
        printf("teststruct element is %d in printtest\n", teststruct->element);
        printf("Number is %d\n", *number);
        free(teststruct);
    }

int main()
{
    int number;
    struct structexample teststruct;
    initStruct(&teststruct, &number);
    printtest(&teststruct, &number);
    printf("teststruct element is %d in main()", teststruct.element);
    return 0;
}

这会产生:

teststruct element is 10 in initStruct
teststruct element is -7967792 in printtest
Number is 5
Segmentation fault

我用 "gcc -Wall -pedantic -ansi" 编译程序,没有收到任何错误或警告。

当我注释掉 "malloc" 和 "free" 时,它会正确生成:

teststruct element is 10 in initStruct
teststruct element is 10 in printtest
Number is 5

如果我只注释掉 "free" 但保留 "malloc" ,这修复了分段错误,但结构的值仍然不正确。在这个简单的程序中,我并不真正需要 "malloc()" 和 "free()",但在我的大型项目中确实需要它们。如果我能让它们在这个更简单的程序中工作,那么我想我可以修复更大的程序。不幸的是,我在 Google 上找不到类似的问题。

您正在混合堆栈和堆

void initStruct(struct structexample * teststruct, int * number)
 {
     teststruct = malloc(sizeof(struct structexample)); 
     ^ There is no need to use malloc, teststruct is on the stack

 ...

int main()
{
    int number;
    struct structexample teststruct;
    initStruct(&teststruct, &number);
void initStruct(struct structexample * teststruct, int * number)
{
    teststruct = malloc(sizeof(struct structexample)); 
    teststruct->element = 10;
    printf("teststruct element is %d in initStruct\n", teststruct->element);
    *number = 5;
}

你给这个函数传递了一个值,一个结构的地址,它完全忽略了。它使用 malloc 进行分配,但对它返回的地址不执行任何操作。它没有 return 它。它不会把它放在其他代码可以得到它的任何地方。所以你刚刚泄露了这个对象。

void printtest(struct structexample * teststruct, int * number)
{
    printf("teststruct element is %d in printtest\n", teststruct->element);
    printf("Number is %d\n", *number);
    free(teststruct);
}

所以 printtestteststruct 传递给 free,因此它应该从 malloc.

传递一个值 return
struct structexample teststruct;
initStruct(&teststruct, &number);
printtest(&teststruct, &number);

但是你把printtest的地址传给了teststruct,它是在栈上分配的。这不可能是对的。

您是否期待 initStruct 以某种方式移动 teststruct?肯定不行。

只需从 printtest() 中删除 free() 行,使其看起来像这样:

void printtest(struct structexample * teststruct, int * number)
{
    printf("teststruct element is %d in printtest\n", teststruct->element);
    printf("Number is %d\n", *number);
}

发生分段错误是因为您试图释放堆栈上的内存!!

您还可以从 initStruct() 中删除 malloc() 行,因为它没有用:它正在为 struct structexample 分配 space 并将其地址返回到 [=16] =] wich 是在堆上分配的 struct structexample * 并传递给 initStruct(),这意味着一旦调用 initStruct() returns.

它将丢失