自分ではメモリ解放しているつもりなんですが,メモリがどんどん埋まっていきます.
どこが間違っているのでしょうか?
大雑把に書くと下のようなコードを書いてます.
void debug(char** filepath){
ifstream fin;
unsigned char* buf;
for(int i=0;i<=100;i++){
buf = new unsigned char[40000000];
fin.open(filepath, ios::binary);
fin.read((char*)buf,40000000);
fin.close();
delete [] buf;
}
}
ifstreamとreadのメモリリーク
Re: ifstreamとreadのメモリリーク
メモリの使用量はどのようにして計測していますか?
Re: ifstreamとreadのメモリリーク
linuxなので,別窓のターミナル上で
$ free -s 1
として1秒ごとのメモリ使用状況を確認しています.
ちなみに下の例ではメモリリークは起こっていません.
どうも解放できてないのは配列のbufの方ではなく,ifstream finの方なのですが,
finもreadをしなければメモリが溜まっていくわけでは無いようです.
void debug(char** filepath){
ifstream fin;
unsigned char* buf;
for(int i=0;i<=100;i++){
buf = new unsigned char[40000000];
fin.open(filepath, ios::binary);
// fin.read((char*)buf,40000000);
fin.close();
for(int k=0;k<=40000000;k++)
buf[k] = 255;
delete [] buf;
}
}
$ free -s 1
として1秒ごとのメモリ使用状況を確認しています.
ちなみに下の例ではメモリリークは起こっていません.
どうも解放できてないのは配列のbufの方ではなく,ifstream finの方なのですが,
finもreadをしなければメモリが溜まっていくわけでは無いようです.
void debug(char** filepath){
ifstream fin;
unsigned char* buf;
for(int i=0;i<=100;i++){
buf = new unsigned char[40000000];
fin.open(filepath, ios::binary);
// fin.read((char*)buf,40000000);
fin.close();
for(int k=0;k<=40000000;k++)
buf[k] = 255;
delete [] buf;
}
}
Re: ifstreamとreadのメモリリーク
コードの貼り付け方を理解しておりませんでした.
同じコードを載せておきます.
ちなみにchar** filepathで送られてきているのはtif画像のアドレスです.
メモリ解放できていない
メモリ解放できている
同じコードを載せておきます.
ちなみにchar** filepathで送られてきているのはtif画像のアドレスです.
メモリ解放できていない
void debug(char** filepath){
ifstream fin;
unsigned char* buf;
for(int i=0;i<=100;i++){
buf = new unsigned char[40000000];
fin.open(filepath[i], ios::binary);
fin.read((char*)buf,40000000);
fin.close();
delete [] buf;
}
}
Re: ifstreamとreadのメモリリーク
本当にリークしているかどうか怪しいのでvalgrindなどを使ってチェックしてみてください。
Re: ifstreamとreadのメモリリーク
結果を書きます.
LEAK SUMMARYは出ませんでしたが,HEAP SUMMARYで
1,488 allocs, 1,488 frees, 3,000,989,266 bytes allocated
となっており,メモリ取得,解放数が同じなのに3GBもメモリを獲得したままになっています(という認識でいいのでしょうか?).
Conditional jump or move depends on uninitialised value(s)は
対象コードをコメントアウト化して消しても変わらなかったため省略しました.
いまいちこの結果の見方もよくわかっていないのですが,これはメモリリークではないのでしょうか?
LEAK SUMMARYは出ませんでしたが,HEAP SUMMARYで
1,488 allocs, 1,488 frees, 3,000,989,266 bytes allocated
となっており,メモリ取得,解放数が同じなのに3GBもメモリを獲得したままになっています(という認識でいいのでしょうか?).
Conditional jump or move depends on uninitialised value(s)は
対象コードをコメントアウト化して消しても変わらなかったため省略しました.
いまいちこの結果の見方もよくわかっていないのですが,これはメモリリークではないのでしょうか?
$ valgrind --leak-check=full --leak-resolution=high --show-reachable=yes ./main -AM 100 config.txt
==11319== Memcheck, a memory error detector
==11319== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==11319== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==11319== Command: ./main -AM 100 config.txt
==11319==
/* 中略 */
program will start with AM=100 and
config.txt
==11319== Syscall param open(filename) points to unaddressable byte(s)
==11319== at 0x57430A0: __open_nocancel (syscall-template.S:81)
==11319== by 0x56D1A47: _IO_file_fopen@@GLIBC_2.2.5 (fileops.c:228)
==11319== by 0x56C5F23: __fopen_internal (iofopen.c:90)
==11319== by 0x4EB2B5F: std::__basic_file<char>::open(char const*, std::_Ios_Openmode, int) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==11319== by 0x4EEB039: std::basic_filebuf<char, std::char_traits<char> >::open(char const*, std::_Ios_Openmode) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==11319== by 0x4EEC12F: std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(char const*, std::_Ios_Openmode) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==11319== by 0x4042AB: debug(config&) (main.cpp:308)
==11319== by 0x402840: main (main.cpp:54)
==11319== Address 0x5a39c68 is 24 bytes inside a block of size 73 free'd
==11319== at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11319== by 0x4EF14DE: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==11319== by 0x409C1B: IOsetting::filepath(int) (LoadConfig.cpp:110)
==11319== by 0x404294: debug(config&) (main.cpp:308)
==11319== by 0x402840: main (main.cpp:54)
==11319==
==11319==
==11319== HEAP SUMMARY:
==11319== in use at exit: 0 bytes in 0 blocks
==11319== total heap usage: 1,488 allocs, 1,488 frees, 3,000,989,266 bytes allocated
==11319==
==11319== All heap blocks were freed -- no leaks are possible
==11319==
==11319== For counts of detected and suppressed errors, rerun with: -v
==11319== Use --track-origins=yes to see where uninitialised values come from
==11319== ERROR SUMMARY: 4194 errors from 20 contexts (suppressed: 0 from 0)
Re: ifstreamとreadのメモリリーク
リークはしていないようですね。最終的に確保しているサイズは in use at exit: 0 bytes in 0 blocks となっています。
3,000,989,266 bytes は total heap usage ですのでアロケートしたサイズの合計です。
3,000,989,266 bytes は total heap usage ですのでアロケートしたサイズの合計です。
Re: ifstreamとreadのメモリリーク
リークではないのにプログラム終了後もメモリ解放されないということはあるのでしょうか?
コードを手直ししていたらエラーは全部とれてしまいました.
プログラム実行前後のfreeコマンドの結果も貼ります.
コードを手直ししていたらエラーは全部とれてしまいました.
valgrind --leak-check=full --leak-resolution=high --show-reachable=yes ./main -AM 0 config.txt
==2621== Memcheck, a memory error detector
==2621== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==2621== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==2621== Command: ./main -AM 0 config.txt
==2621==
program will start with AM=0 and
config.txt
==2632== h-nozomu
==2632== HEAP SUMMARY:
==2632== in use at exit: 0 bytes in 0 blocks
==2632== total heap usage: 8,508 allocs, 8,508 frees, 20,419,180,105 bytes allocated
==2632==
==2632== All heap blocks were freed -- no leaks are possible
==2632==
==2632== For counts of detected and suppressed errors, rerun with: -v
==2632== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
ino-n% free [~]
total used free shared buffers cached
Mem: 7896288 869276 7027012 36020 1360 141076
-/+ buffers/cache: 726840 7169448
Swap: 8102908 0 8102908
ino-n% free [~]
total used free shared buffers cached
Mem: 7896288 7647444 248844 36952 8276 6687616
-/+ buffers/cache: 951552 6944736
Swap: 8102908 0 8102908
ino-n%
Re: ifstreamとreadのメモリリーク
Linuxトラブルシューティング探偵団 番外編(1):減り続けるメモリ残量! 果たしてその原因は!? (2/3) - @IT
システムが利用可能なメモリ量を計算するには、Linuxのページキャッシュの扱いを理解する必要があります。LinuxはHDDなどのストレージに保存してあるデータの読み出し/書き出し時に確保したメモリをページキャッシュという形で保持します。
CPU はストレージのデータを直接読むことはできません。そのため、ストレージデータはまずはメモリにロードする必要があります。Linuxでは、こうして読み込んだデータをページキャッシュとして再利用しています。いったん作成してしまえば、ページキャッシュは読み出し/書き出しにストレージを介さないため、非常に高速に動作します。
ページキャッシュは新たなストレージデータの読み出し/書き出し要求などがあってメモリが必要とならない限り、メモリを解放しません。そのため、通常はシステムが稼働しているだけでMemFreeはページキャッシュとして活用されていき、ある程度までは減り続けます。
Re: ifstreamとreadのメモリリーク
配列の確保された領域の範囲外にアクセスしています。規格は知らないですが、危険な未定義動作かもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)