【问题标题】:Segmentation fault after realloc(). Can't assign allocated memory to pointerrealloc() 之后的分段错误。无法将分配的内存分配给指针
【发布时间】:2012-04-25 07:00:50
【问题描述】:

我正在尝试使用 realloc() 分配一些内存。到目前为止,这有效。但是,如果我想将分配的内存分配给结构变量中的指针,则会出现分段错误:

// in header
typedef struct {
    int a;
    char test[20];
} MyContent;

typedef struct {
    MyContent* values; 
    // simmilar to: MyContent values[]
    // ... some other stuff
} MyData;

// in source
void myFunction(MyData* dataPtr) {
    dataPtr->values = NULL;
    MyData* tempPtr = NULL;

    for (int i = 1; i < 10; i++) {
        tempPtr = (MyContent*) realloc(dataPtr->values, i * sizeof(MyContent));
        if (tempPtr == NULL) {
            free(dataPtr->values);
            break;
        }
        dataPtr->values = tempPtr;  // Here I get the segmentation fault
        dataPtr->values[(i-1)].a = 42;
        // ...
    }
}

我不知道这里出了什么问题。有什么建议么?感谢您的帮助。

【问题讨论】:

  • 错误出现在您未粘贴的代码中。上面的代码只有一个重要的问题——它错误地处理了realloc 返回NULL 的情况。如果您可以发布一个完整的、可编译的示例来显示错误,我们可能会为您找到它。否则,请在您的代码上运行 valgrind。 (顺便问一下,这是 C 代码还是 C++ 代码?你把两个标签都放了,这很混乱。)
  • @DavidSchwartz,OP 发布的代码可以在 C 或 C++ 下编译和运行就好了 :)
  • @bdonlan:是的,这样就不可能知道他在问什么。例如,如果我要对其进行测试,我应该将其作为 C 代码还是 C++ 代码进行测试?如果我要建议修复/更改,它们应该是 C 代码还是 C++ 代码?
  • @DavidSchwartz,您可以将自己限制在 C 和 C++ 的交集上,这基本上是 C 的大部分内容(有一些细微差别)。确定使用哪个 OP 会有所帮助,但在不知道的情况下尝试提供帮助并非不可能。只是不要假设 void* 自动转换,也不要将变量命名为 class :)
  • @user1355415,我认为你的最后一次编辑实际上让事情变得更糟 - 你的演员表与现在的 sizeof 一致,但你分配给 dataPtr-&gt;values 仍然是 MyContent*...跨度>

标签: c pointers segmentation-fault realloc


【解决方案1】:

好像你编辑了你的代码。编辑后的代码运行良好。

#include<stdio.h>
#include<malloc.h>
#include<string.h>
// in header
typedef struct {
    int a;
    char test[20];
} MyContent;

typedef struct {
    MyContent* values; 
    // simmilar to: MyContent values[]
    // ... some other stuff
} MyData;

// in source
void myFunction(MyData* dataPtr) {
    dataPtr->values = NULL;
    MyData* tempPtr;

    for (int i = 1; i < 10; i++) {
        tempPtr = (MyData*) realloc(dataPtr->values, i * sizeof(MyContent));
        if (tempPtr == NULL) {
            if(dataPtr->values)
                free(dataPtr->values);
            printf("realloc() failed\n");
            return ;
        }
        dataPtr->values = (MyContent*)tempPtr;  // Here I get the segmentation fault
        dataPtr->values[(i-1)].a = 42+i;
        strcpy(dataPtr->values[(i-1)].test,"name");
    }
}

void PrintData(MyData* dataPtr) {
    for (int i = 1; i < 10; i++)
        printf("We have %s at %d\n",dataPtr->values[(i-1)].test,dataPtr->values[(i-1)].a);
}

main() {
    MyData Sample;
    myFunction(&Sample);
    PrintData(&Sample);
}

【讨论】:

  • 对不起,在你所有的答案中代码的变化。我试图解决所有不必要的问题来解决问题。这样做我可能会以错误的方式遗漏或更改某些内容。我意识到我传递给myFunction() 的论点是错误的,由于您在此处的示例帖子,我现在发现了这一点。谢谢大家 - 伟大和超快速的支持。
【解决方案2】:

乍一看,我没有看到可能导致崩溃的问题 - 基于一的寻址有点奇怪,但并非不正确。代码中可能存在您未显示的问题,导致堆或堆栈损坏,而 realloc 调用会使情况变得更糟。或者,如果您正在使用优化进行编译,您的调试器可能会对崩溃实际发生的位置感到困惑。您还混淆了MyDataMyContent,但我认为这只是因为您在编辑代码时出错了。

还要注意,如果realloc 失败,您将在您指定的行 之后崩溃,因为您将写入一个空指针。如果tempPtr is NULL,您需要中止,而不仅仅是释放旧指针。但是,这再次导致与您指示的线路不同的故障。

我建议在 valgrind 下运行您的程序,看看它报告错误的位置 - 第一个发生的此类错误很可能是罪魁祸首。

【讨论】:

  • 是的,我在 realloc() 语句中混淆了 MyData 和 MyContent。对不起,我更正了。我还省略了break,这引起了额外的混乱。
【解决方案3】:

您检查新分配的内存的条件是错误的。应该是:

if (tempPtr == NULL) {
  // handle error condition or continue with original 'dataPtr->values'
}
else {
  dataPtr->values = tempPtr;
}

请记住,realloc() 不一定将一个块转移到另一个块。有时它可能会在同一个指针区域分配内存。

【讨论】:

  • 这是不正确的。如果旧指针发生了变化,则不能释放它; realloc 已经为你处理好了。
  • reallocate 函数将释放旧块本身。你不能释放它。
  • 谢谢,不知道,realloc() frees 旧块本身。
猜你喜欢
  • 2016-01-02
  • 2021-09-02
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 2021-11-25
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
相关资源
最近更新 更多