【问题标题】:glibc detected - double free or corruption (!prev)检测到 glibc - 双重释放或损坏 (!prev)
【发布时间】:2014-10-22 14:40:45
【问题描述】:

我收到了您可能在标题中看到的错误,我不知道为什么。

代码:

#include <cstdlib>
#include <cstdio>

struct CData {
    int* num;
    char* adr;
    char* ph;

    void (*init)(CData* owner);
    void (*del)(CData* owner);
    char* (*getAdr)(CData* owner);
    void (*setAdr)(CData* owner, char* adr);
};

void CData_init(CData* owner) {
    owner->num = (int*)malloc(sizeof(int));
    owner->adr = (char*)malloc(sizeof(char)*255);
    owner->ph = (char*)malloc(sizeof(char)*255);
}

void CData_del(CData* owner) {
    free(owner->num);
    free(owner->adr);
    free(owner->ph);
}

char* CData_getAdr(CData* owner) {
    return owner->adr;
}

void CData_setAdr(CData* owner, char* adr) {
    owner->adr = adr;
}

int main() {
    CData* data = (CData*)malloc(sizeof(CData));

    data->init = CData_init;
    data->del = CData_del;
    data->getAdr = CData_getAdr;
    data->setAdr = CData_setAdr;

    data->init(data);

    data->setAdr(data, "asdasd");
    printf("%d", data->getAdr(data));

    data->del(data);

    free(data); 

    return 0;
}

所以我认为错误是由 char* 操作引起的,但我不知道为什么。

我想要做的是我希望它能够将一个字符串作为参数传递给data-&gt;setAdr,然后我希望它被分配给变量。

编译行:

gcc -o test main.cpp

【问题讨论】:

  • "double free" - 这应该告诉你一些事情,也许是像 "double free()"
  • 你不能释放字符串文字。 (而且您在 setAdr 中泄露了之前的值。)
  • 是的,我一开始也是这么猜测的,但是在哪里呢?
  • 那我该如何释放内存呢?我应该吗?
  • 你为什么使用 C++ 编译器来编译 C 代码?

标签: c


【解决方案1】:

data-&gt;setAdr(data, "asdasd"); 有问题。

您正在设置不是由 malloc 分配的内存块的地址,然后尝试使用free 释放它。释放除 NULL 指针之外的此类内存块(不是由 malloc 分配的)会导致未定义的行为。

在您的情况下,这也会泄漏至少 255 字节的内存。 valgrind 可以帮助您更好地理解这种情况。

更改以下功能应该可以解决此问题(适当重命名)

void CData_setAdr(CData* owner, char* adr) {
    strcpy(owner->adr, adr);  /* include cstring */
}

【讨论】:

  • 所以在我的情况下,我需要简单地存储一个指向静态字符串的指针而不关心内存分配?
  • 在这种情况下,您不应该将字符串的所有权授予CData,而 setter 应该分配和释放字符串。您不能跨模块混合分配和释放规则。要启用这两种设置方式,您需要稍微多一点的框架来检测何时释放和何时不释放。
  • 您的意思是strcpy 而不是strcmp?
【解决方案2】:

问题出在这里:

data->setAdr(data, "asdasd");

你的实现是:

void CData_setAdr(CData* owner, char* adr) {
    owner->adr = adr;
}

因此,您使用指向常量字符串的指针覆盖先前malloc()ed 内存的地址,因此当您执行data-&gt;del(data); 时,glibc 警告您正在释放未分配的内存,加上先前分配的内存丢失。试试吧:

void CData_setAdr(CData* owner, char* adr) {
    strcpy(owner->adr, adr);
}

记得添加合适的错误检查等!

【讨论】:

    猜你喜欢
    • 2010-10-27
    • 2012-05-20
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    相关资源
    最近更新 更多