2016-08-14 9 views
1

私は、JNIで使用される単純なC/C++コードを適応しようとするC/C++の経験がほとんどないJavaプログラマーです。無料でcallocを安全に使用できますか?

私は、単一のcalloc()で割り当てられた配列(または他のメモリチャンク)は、mallocから返されるSAMEポインタを持つ単一のfree()呼び出しで常に解放されるべきであると読んでいます。それはfree'dでない場合、メモリリークを引き起こします。

私が適応しているC/C++コードはcalloc()を使用していますが、対応するfree()呼び出しはありません。 free()呼び出しをしてはならない状況があるか、コードがひどく書かれていますか?

+6

私には壊れた/怠惰な音。 –

+3

メモリを割り当てたら、解放する必要があります。例外なく。それ以外の場合はメモリリークを取得します。 – ForceBru

+0

**ヒープ再利用性**を向上させるには、 'free()'を使うのは良い考えです。それ以外の場合、大規模なソフトウェアの場合は、**ヒープ**または**フリーストア(C++レキシコン内)**が使い果たされ、残りは災害になります。 –

答えて

3
calloc(...)または malloc(...)には、対応する free()が必ず付いていなければなりません。そのため、アプリケーション/ OSは他の目的でメモリを再利用できます。メモリを解放しないアプリケーションは、そのメモリを "リーク"させ、そのメモリを使用不能にします。

free()を使用しない場合、わかりやすいオペレーティングシステムでは、アプリケーションが終了したときに再びそのメモリを使用できるようになりますが、OSに依存してメモリリークを解決するプログラムはひどくプログラムされています。

これは(すでに知っているように)これは、使用されていないメモリを定期的にクリーンアップするガベージコレクタを持つJavaとは異なります。

一般的な補足として、同じポインタを使用してメモリを解放する必要はありません。たとえば、あなたがこれを行うことができます:

// Create an array of 10 integers. 
int *x; 
x = calloc(10, sizeof(int)); 

// Create another pointer 'y', which uses the same array as x. 
int *y; 
y = x; 

// Delete the array. Both 'x' and 'y' are unusable now. 
free(y); 
1

これらのオペレーティングシステムは、プログラムが終了したときに割り当てられたメモリを使用しています。しかし、これは、あなたのためにメモリを解放するためにオペレーティングシステムに依存する悪い習慣です。それは明らかにそのひどく書かれています。

1

OSはプロセス終了時にすべてのプロセスリソースを解放しますが、あなたのプログラムがメインループを持ち、frequentyがメモリを割り当てる場合は、それを頼りにするのは良いアイデアではありません。)

2

割り当ては、ライブラリコードとループ内で実行されるコードの割り当て解除と常にペアにする必要があります。

基本的に、未参照の未参照メモリが累積されず、それによってプロセスのメモリ消費が増加しないようにします。

単純に終了したいときに割り当て解除をスキップすることは許容されますが(一般的には嫌なことですが)、割り当てをたくさんやることがあれば少し早くすることができます。 C++で

、割り当ておよび割り当て解除はデストラクタ(RAII)を介して、暗黙的に対にすることができる。実際に

#include <utility> 
#include <memory> 
#include <stdio.h> 
#include <stdlib.h> 

struct Free{ 
    void operator() (void* x){ 
     free(x); 
    } 
}; 

int main(){ 
    char *p = new char; 
    delete p; //an explicit deallocation 

    std::unique_ptr<char, Free> ptr { (char*)calloc(1,100) }; 
    return 0; 
    //an implicit deallocation 
    //-- you don't see the free but unique_ptr's destructor does call it here 
} 

を、デストラクタに依存するC++でダイナミックメモリを扱う絶対好ましい方法です。

valgrindなどのツールを使用して、プログラムの実行中に割り振りと割り当て解除がペアになっていることを確認できます(g ++標準ライブラリは最初に直接的または間接的にnewを呼び出したときに、私は経由して上記のプログラムを実行するとfree秒)

と一致する必要があります。

valgrind ./a.out 

私が取得:

==25629== Memcheck, a memory error detector 
==25629== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==25629== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==25629== Command: ./a.out 
==25629== 
==25629== 
==25629== HEAP SUMMARY: 
==25629==  in use at exit: 72,704 bytes in 1 blocks 
==25629== total heap usage: 3 allocs, 2 frees, 72,805 bytes allocated 
==25629== 
==25629== LEAK SUMMARY: 
==25629== definitely lost: 0 bytes in 0 blocks 
==25629== indirectly lost: 0 bytes in 0 blocks 
==25629==  possibly lost: 0 bytes in 0 blocks 
==25629== still reachable: 72,704 bytes in 1 blocks 
==25629==   suppressed: 0 bytes in 0 blocks 
==25629== Rerun with --leak-check=full to see details of leaked memory 
==25629== 
==25629== For counts of detected and suppressed errors, rerun with: -v 
==25629== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 

これは、標準ライブラリ(72,704バイトのもの)による割り当てだけが割り当て解除と対になっていないため、すべてが正常であることを意味します。

0

malloc()などを使用する場合は、例外なく、free()を呼び出す必要があります。しかし、あなたが知っておくべきことは、プログラムの振る舞いにあまりにも不確定性があり、メモリリークに関連するバグが多すぎるため、ダイナミックメモリを決して使うべきではないということです。 MISRA/C標準と他の安全に重要な組み込み標準(これも重要ではない主流のx86ソフトウェアにも適用する必要があります)に述べられているように、mallocは厳密に禁止されています。ソフトウェアで高い信頼性を達成するには、静的メモリのみを使用して開始します。大きな静的配列を事前に割り当てるだけで、すべての心配はなくなりました。

関連する問題