【问题标题】:Malloc() and free() stopping me from passing structs by value in CMalloc() 和 free() 阻止我在 C 中按值传递结构
【发布时间】:2016-02-29 18:13:37
【问题描述】:

我正在做一个项目,我不断收到分段错误,并且结构的值没有被传递。弄清楚为什么让我发疯。我试过用更简单的程序来解决问题,我想我已经找到了问题,但我不知道如何解决它。

问题是当我“malloc”一个结构时,然后按值传递,值就会丢失。稍后添加“免费”会产生分段错误。我不想从“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 上找不到类似的问题。

【问题讨论】:

  • Ansi C 已过时。使用 C99 或 C11。编译所有警告和调试信息(gcc -Wall -Wextra -g 可能还有-std=c99)。如果在 Linux 上,请了解 valgrind 并使用 gdb(它有观察点)。

标签: c ansi-c


【解决方案1】:

你正在混合堆栈和堆

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);

【讨论】:

  • 谢谢!我遇到了另一个问题,我已通过编辑将其添加到此问题中。你能帮我解决这个问题吗?
【解决方案2】:

只需从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 分配空间并将其地址返回到teststruct,这是在堆上分配并传递的struct structexample *initStruct(),这意味着一旦对initStruct() 的调用返回,它就会丢失。

【讨论】:

  • 谢谢!我遇到了另一个问题,我已通过编辑将其添加到此问题中。你能帮我解决这个问题吗?
  • 如果它正在读取您想要的空格分隔的单词,请使用fscanf(),它会这样做。在while 循环中使用feof() 测试文件结尾,以使用fscanf() 读取单词。
【解决方案3】:
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 进行分配,但对返回的地址不做任何事情。它不返回它。它不会把它放在任何其他代码可以得到它的地方。所以你刚刚泄露了这个对象。

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 返回的值。

struct structexample teststruct;
initStruct(&teststruct, &number);
printtest(&teststruct, &number);

但是你将printtest 传递给teststruct 的地址,这个地址是在栈上分配的。这不可能。

您是否期望initStruct 以某种方式移动teststruct?它肯定做不到。

【讨论】:

  • 啊,我想我现在明白了。 “Malloc”改变了指向“teststruct”的指针指向的位置,这与传递给函数的指针不同。不过,我对现在应该在哪里进行 malloc 感到困惑。我写过“&teststruct = malloc(sizeof(struct structexample));”在函数之外,但这会产生错误“ lvalue required as left operand of assignment”。
  • struct structexample* teststruct = malloc ... 怎么样?
  • 我必须把它分成两行,因为我不能混合声明和代码,但那行得通!谢谢。
  • 我遇到了另一个问题。我已通过编辑将其添加到此问题中。你能帮我解决这个问题吗?
  • 您认为sizeof(*fp) 会做什么?我认为您对sizeof 的作用存在严重误解。要么你不明白FILE 是什么——它是你用来访问打开的文件的东西。因为*fpFILE,那么sizeof(*fp) 是在说“我用来访问这个打开的文件的东西有多大”。这跟什么有什么关系?
猜你喜欢
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 2014-01-22
  • 2012-05-19
  • 2015-01-21
  • 2011-02-14
  • 1970-01-01
相关资源
最近更新 更多