ちょっとメモ
以下のようなコードを書いて失敗した。
#include <boost/shared_ptr.hpp> #include <unicode/uclean.h> #include <unicode/ucnv.h> int main() { UErrorCode status = U_ZERO_ERROR; u_init(&status); // (snip) boost::shared_ptr<UConverter> ucnv(ucnv_open("Shift_JIS", &status), ucnv_close); // (snip) u_cleanup(); }
u_cleanup より後に ucnv_close が呼ばれてしまうのが問題。
valgrind で検出
このコード問題があるのに、普通にエラーも何もでないので気が付かない。 valgrind を使ったら、 still reachable なメモリがあると教えてくれた。
$ valgrind ./a.out ==17685== Memcheck, a memory error detector. ==17685== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al. ==17685== Using LibVEX rev 1658, a library for dynamic binary translation. ==17685== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP. ==17685== Using valgrind-3.2.1, a dynamic binary instrumentation framework. ==17685== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al. ==17685== For more details, rerun with: -v ==17685== ==17685== ==17685== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 7 from 1) ==17685== malloc/free: in use at exit: 24,944 bytes in 4 blocks. ==17685== malloc/free: 8 allocs, 4 frees, 25,376 bytes allocated. ==17685== For counts of detected errors, rerun with: -v ==17685== searching for pointers to 4 not-freed blocks. ==17685== checked 285,112 bytes. ==17685== ==17685== LEAK SUMMARY: ==17685== definitely lost: 0 bytes in 0 blocks. ==17685== possibly lost: 0 bytes in 0 blocks. ==17685== still reachable: 24,944 bytes in 4 blocks. // ←ここ! ==17685== suppressed: 0 bytes in 0 blocks. ==17685== Reachable blocks (those to which a pointer was found) are not shown. ==17685== To see them, rerun with: --show-reachable=yes
修正
で、さっきのコードを以下のようにすればいい。
#include <boost/shared_ptr.hpp> #include <unicode/uclean.h> #include <unicode/ucnv.h> struct ICUInitializer { ICUInitializer() : status_(U_ZERO_ERROR) { u_init(&status_); } ~ICUInitializer() { u_cleanup(); } UErrorCode status_; }; int main() { ICUInitializer init; // (snip) UErrorCode status = U_ZERO_ERROR; boost::shared_ptr<UConverter> ucnv(ucnv_open("Shift_JIS", &status), ucnv_close); // (snip) }
valgrind で確認
$ valgrind ./a.out ==17834== Memcheck, a memory error detector. ==17834== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al. ==17834== Using LibVEX rev 1658, a library for dynamic binary translation. ==17834== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP. ==17834== Using valgrind-3.2.1, a dynamic binary instrumentation framework. ==17834== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al. ==17834== For more details, rerun with: -v ==17834== ==17834== ==17834== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 7 from 1) ==17834== malloc/free: in use at exit: 0 bytes in 0 blocks. ==17834== malloc/free: 8 allocs, 8 frees, 25,376 bytes allocated. ==17834== For counts of detected errors, rerun with: -v ==17834== All heap blocks were freed -- no leaks are possible.
まとめ
valgrind で多い日も安心!