

プログラムaをシェルスクリプトを用いて同時に複数回、バックグラウンドで実行している中で以下のようなエラーが出ます。

> *** Error in `a': double free or corruption (!prev): 0x00000000009120b0 ***

このエラーはメモリの二重開放が原因だと認識しています。  
ここでプログラムa はc言語で書かれており、mallocとfreeを用いてメモリの動的確保をしています。

[code]

    #define SAFE_FREE(ptr) { free(ptr); ptr = NULL; } 
    
    j=(double *)malloc( sizeof( double ) * MAX );
    pow=(double *)malloc( sizeof( double ) * MAX );
    
    SAFE_FREE(j);
    SAFE_FREE(pow);
    
    
[/code]

上記のようにメモリの二重開放には、使い終わったポインタにNULLを代入することで対策していたのですが依然として二重開放によるエラーが見られるので困っています。

上記のプログラムに問題があるでしょうか？バックグラウンドで複数回同時に実行していることが原因なのでしょうか？その場合の対策方法など、ご存じの方はご教授いただきたいです。

ありがとうございます。


CC BY-SA 4.0
2020-09-13T04:52:31.307
70340
2020-09-13T09:10:09.847
2020-09-13T09:00:14.603
4236
40283
question
c
バックグラウンド処理でのメモリの二重開放への対策について


SAFE_FREEが「メモリの２重開放を防止する」マクロになっていません。  
SAFE_FREEを複数回呼び出すと、２回目のSAFE_FREEでfree(NULL)を呼び出すことになります。

[code]

    SAFE_FREE(x);
    SAFE_FREE(x);
    
[/code]

SAFE_FREEの処理は以下の機能が必要です。

  * freeしたポインタがfree済みであることを明確にするため、NULLポインタを代入しておく
  * 指定されたポインタがNULLポインタでないときだけfreeする

例

[code]

    #define SAFE_FREE(ptr) { if(ptr!=NULL)free(ptr); ptr = NULL; } 
    
[/code]

※上の例は実際に試したわけではありません。

* * *

コメントをいただいたのでfree(NULL)について調べてみました。

> free(NULL)をした場合何も実行されないです

結論からいうと、質問された方の現象は別の原因で発生した可能性が非常に高いです。  
Ubuntu 18.04.5 LTSで試してみましたが、問題は発生しませんでした。

C99(§7.20.3.2) で`If ptr is a null pointer, no action occurs.`と書かれています。  
GNU 2017-09-15 MALLOC(3)も`If ptr is NULL, no operation is performed.`も同じです。

`if(ptr)free(ptr)`の是非についてはいろいろな見解があるようです。

  * すべての処理系で安全とは限らない
  * 古い慣習にとらわれるべきでない
  * 不要なコードはコードを読むときに邪魔
  * freeを呼び出すオーバヘッドが減る ※効果が軽微、安全性とは無関係との反論がありました
  * NULLチェックしてからポインタ変数を使用するのは良い習慣


CC BY-SA 4.0
2020-09-13T05:33:08.980
70341
2020-09-13T07:10:06.693
2020-09-13T07:10:06.693
35558
35558
70340
answer


提示コードは質問のためのコードだと思いますが、ここだけでは問題のあるところは無さそうに見えます。  
問題が再現するコードを提示することが出来れば、誰かが問題を見つけられるかもしれません。

malloc()でエラーチェックを指定していないことが気になりますが、(NULLが返ってきたらおそらくその先の処理は意図通りに動かせないと思います。)  
SAFE_FREEマクロ自体は問題は無いと思います。

可能性としてぱっと思いつくのは、  
・不正メモリアクセスしてポインタ変数を破壊してしまっている。  
・malloc()したポインタ変数を別のところで別のポインタ変数にコピーしていて、最終的に両方でSAFE_FREEしてしまっている。  
とかでしょうか。

あともう1点、

> バックグラウンドで複数回同時に実行していることが原因なのでしょうか？

複数実行されるプロセス同士は独立したメモリ空間で実行されるためmalloc()されたポインタが  
干渉するようなことはありません。


CC BY-SA 4.0
2020-09-13T05:53:54.467
70343
2020-09-13T06:01:49.477
2020-09-13T06:01:49.477
30745
30745
70340
answer


> プログラムaをシェルスクリプトを用いて同時に複数回、バックグラウンドで実行している中で以下のようなエラーが出ます。

プログラムはプロセスという単位で管理されており、あるプロセスの問題が他のプロセスに影響を及ぼすことはほとんどありません。そのため、bashから起動したとか複数回実行したとかバックグラウンドで実行したとかは関係ありません。プログラムそのものの問題です。

> このエラーはメモリの二重開放が原因だと認識しています。

問題の本質を理解できていません。二重開放それ自身が問題というわけではありません。メモリを使用しないと判断し一度は解放したにも関わらず、
**実は使用され続けていた** 。その後、もう一度使用しないと判断されて解放処理が行われた、という状況です。

是正すべきはメモリの使用状況を適切に管理することです。


CC BY-SA 4.0
2020-09-13T09:10:09.847
70346
2020-09-13T09:10:09.847
4236
70340
answer