1

尝试释放在 c 函数内部分配的对象的内存(在 Objective-c 代码中)时,我收到“malloc:*对象 0xbfffe160 的错误:未分配被释放的指针”。这个 C 函数创建并返回二进制数据包,稍后用作 NSData。这是我的 obj-c 代码部分,我在其中创建结构变量并通过引用 C 函数将其传递:

MyPacket packetRef;
allocAuthentificationCodePacket(&packetRef);

NSData *data = [NSData dataWithBytes:packetRef.bytes length:packetRef.packet->packetSize];
free(&packetRef); // getting error

一切正常,除了我试图释放内存,因为数据应该由 NSData 变量保留。C 函数在自身内部执行 calloc,所以我应该以某种方式释放该内存:

packetRef->bytes = calloc(1, sizeof(*packetRef));

这是我存储二进制数据的结构:

typedef struct {

  uint8_t packetType;
  uint16_t packetBody;

} MyStruct;

和另一个结构:

typedef union {

  const uint8_t *bytes; 
  MyStruct *packet;

} MyPacket;

我应该如何释放内存?我得到的错误不是崩溃,它只是运行单元测试时调试控制台中的一条消息。

更新。试图释放“字节”结构成员但得到相同的错误消息:

free(&packetRef.bytes);

更新2。谢谢,建议的方法确实有效,并且 malloc 错误消息从控制台中消失了:

free(packetRef.bytes);

但是,在 Xcode 中收到警告“将 'const uint8_t *' (aka 'const unsigned char *') 传递给 'void *' 类型的参数会丢弃限定符”。我正在使用 Apple LLVM 4.1 编译器。C 函数驻留在单独的文件中,并且只包含一个标头,因为 Android 人员将不得不重用它。

更新3。感谢@simonc 和@nos 指出结构成员“bytes”具有常量。删除 const 后警告消失了。使用 const 的最初想法是保护“字节”不被修改。

4

2 回答 2

3

总是错误的。&(提示:放在 .里面 几乎总是错误的free()。)

MyPacket packetRef;
...
free(&packetRef); // getting error

不管是什么MyPacket——它具有自动存储持续时间,即编译器自动分配存储空间并在函数退出时释放它。

不要free()做某事,除非它来自malloc()(或calloc(),等)

由于packetRef.bytes 已分配calloc(),您可以free()改为使用 。

MyPacket packetRef;
allocAuthentificationCodePacket(&packetRef);
...
free(packetRef.bytes);

更新

如果您调用的函数allocAuthentificationCodePacket, 包含以下代码:

packetRef->bytes = calloc(1, sizeof(*packetRef));

如果该bytes字段具有 type const uint8_t *,则有问题。

  1. 也许你的代码是错误的,你应该调用一些函数来释放数据包,而不是自己释放它。

  2. 也许bytes字段的类型是错误的,应该是uint8_t *而不是const uint8_t *.

  3. 也许allocAuthentificationCodePacket是错的。

谁知道?崩溃还不算错,但这一个问题。

脚注

C中没有引用。 &x是“x的地址”,而不是“对x的引用”。

让我们考虑以下代码:

char *x = malloc(10);
free(x);

当人们谈论这段代码时,他们会说“x在堆上分配”之类的东西,但这在技术上是不正确的,x它是在堆栈上分配的,并且包含堆上的 10 个字节的地址。同样,该行free(x)实际上并不 free x,它释放x指向的内存。

因此,当有人告诉您“不要忘记释放x”时,您知道他们实际上的意思是“不要忘记释放其中包含的值x指向的内存”。人们对术语很草率,但计算机却不是。

于 2012-11-06T13:52:13.720 回答
2

packetRefpacketRef->bytes在您的示例中是分配了堆的堆栈变量。因此,您应该致电free(packetRef.bytes)

由于您在函数内部分配内存allocAuthentificationCodePacket- 您可能需要创建另一个函数来释放内存

void freePacket(MyPacket* packet)
{
    free(packet->bytes);
}
于 2012-11-06T13:51:49.523 回答