1

c 関数内で割り当てられたオブジェクトのメモリを (objective-c コードで) 解放しようとすると、「malloc: *オブジェクト 0xbfffe160 のエラー: 解放されるポインターが割り当てられませんでした」というメッセージが表示されます。この C 関数は、後で NSData として使用されるバイナリ データ パケットを作成して返します。これは、構造体変数を作成し、C 関数への参照によって渡す私の obj-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;

メモリを解放するにはどうすればよいですか? 私が得ているエラーはクラッシュではなく、単体テストを実行しているときにデバッグ コンソールに表示されるメッセージです。

更新します。「bytes」構造体メンバーを解放しようとしましたが、同じエラー メッセージが表示されました。

free(&packetRef.bytes);

UPDATE2。ありがとう、提案された方法は機能し、コンソールからmallocエラーメッセージが消えました:

free(packetRef.bytes);

ただし、Xcode で「'const uint8_t *' (別名 'const unsigned char *') をタイプ 'void *' のパラメーターに渡すと、修飾子が破棄されます」という警告が表示されます。Apple LLVM 4.1 コンパイラを使用しています。C関数は別のファイルにあり、Androidの人はそれを再利用する必要があるため、ヘッダーのみが含まれています.

UPDATE3 . 構造体メンバー「bytes」にconstがあることを指摘してくれた@simoncと@nosに感謝します。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 に答える