2012-04-03 12 views
1

異なるスレッド間でグローバルセットを共有しているので、必要なメモリをどれだけ配置するかによってメモリを割り当てます。キンダーのようなバッファ。同じスレッドから解放しようとすると、glibは狂ってsegfaultsになります。mallocとC言語のスレッド間でメモリを解放する

私は遠くにcプログラマーではありません。私は一緒にハッキングしたコードでメモリリークをクリアしようとしています。

char *keybuffer[], *valuesbuffer[], *returnbuffer[], *bufferaction; 
int memcache_lock=1,*bufferelements, bufferowner=0; 


void memcache_clear_buffers(){ 
     free(&bufferaction); //I get the same reaction when I have the & and without the & 
//  free(*keybuffer); //I thought maybe I need to use the pointer. Then 
//  free(*valuesbuffer); // I thought maybe I needed to reference the address in memory. 
//  free(*returnbuffer); // I appreciate any help. 
//  free(*bufferelements); 
} 

void memcache_allocate_buffers(int size){ 
     *keybuffer = (char *)malloc(size * sizeof(char *)); 
     *valuesbuffer = (char *)malloc(size * sizeof(char *)); 
     *returnbuffer = (char *)malloc(size * sizeof(char *)); 
     bufferelements = malloc(sizeof(int)); 
     bufferaction = (char *)malloc(sizeof(char*)); 
} 

ここにはvalgrindの出力があります。

3500== Invalid free()/delete/delete[] 
==3500== at 0x4027C02: free (vg_replace_malloc.c:366) 
==3500== by 0x4191D4C: memcache_clear_buffers (dm_memcache.c:254) 
==3500== by 0x41921ED: memcache_set (dm_memcache.c:328) 
==3500== by 0x4192281: memcache_sid (dm_memcache.c:151) 
==3500== by 0x418316D: db_user_exists (dm_db.c:3208) 
==3500== by 0x403F7F2: auth_user_exists (authsql.c:49) 
==3500== by 0x419ADA6: auth_user_exists (authmodule.c:130) 
==3500== by 0x4040D4E: auth_validate (authsql.c:333) 
==3500== by 0x419B106: auth_validate (authmodule.c:163) 
==3500== by 0x74656CFF: ??? 
==3500== Address 0x41b55c0 is 0 bytes inside data symbol "bufferaction" 

どのように無効な無料ですか?

+0

無料でアンパサンドが間違っています。 'bufferaction'を使う場所を私たちに教えてください。 – cnicutar

+0

他のスレッドからメモリにアクセスしている可能性があるので、これらの 'free()'呼び出しをミューテックスロックするように注意してください。 – Gui13

+0

バッファオーバーフローの可能性もあります。バッファリングに十分なスペースを確保していますか? – w00

答えて

4
  • malloc()およびfree()はスレッドセーフな関数ではありません。これらの関数への呼び出しをmutexで保護する必要があります。
  • すべての共有変数をミューテックスで保護する必要があります。変数ごとに1つ、malloc/freeと同じものを使用できます。
  • いくつかのコンパイラで危険なオプティマイザのバグを防ぐために、複数のスレッド間で共有される変数をvolatileと宣言する必要があります。これはミューテックスガードの代わりではないことに注意してください。
  • バッファ配列、または2次元配列(C文字列の配列など)はありますか?すべてのバッファを潜在的な2次元配列として宣言しましたが、最も内側の次元は決して割り当てません。
  • Cでmallocの結果を型変換しないでください。thisthisを読んでください。
  • free(bufferaction)ではなく、free(&bufferaction)です。
  • すべてのポインタをNULLに明示的に初期化します。 free()の後、ポインタをNULLに設定してください。いずれかのスレッドがメモリにアクセスする前に、ポインタがNULLかどうかを確認してください。
+2

'malloc()'と 'free()'はCライブラリの実装とコンパイラに渡されるフラグによってスレッドセーフです。例えば、この質問を参照してください。http://stackoverflow.com/questions/855763/malloc-thread-safe – JeremyP

+0

@JeremyPスレッドセーフではありません。あなたがその実装について仮定した場合、あなたのコードは移植性がありません。 – Lundin

+1

C99では、一般的な移植可能なスレッドライブラリが存在しなかったので、移植性は本当に問題ではありません。 C11(スレッドを持つ)では、malloc()はスレッドセーフでなければなりません。 – JeremyP

0

あなたはbufferaction(なしアンパサンド)

を解放する必要があるときは、&bufferactionを解放している私はまた、あなたがbufferactionを使用するときにメモリを破壊することができると思います。あなたは、4バイト(または64ビットプラットフォーム用にコンパイルしている場合は8)しか割り当てていないことがわかります。これ以上使用すると、割り当てられたメモリの後にメモリが破壊されてしまいます。これは、内部ヒープ構造を混乱させる可能性があるため、メモリを解放するときにのみ表示されることがあります。

これは並行性に関連するバグではないと私は考えています。

+0

私はこれを3つの方法で試してみましたが、常に無効であると報告しています。 –

関連する問題