2015-04-04 170 views
2

我正在使用clang編譯器和libC++標準庫在C++ 11的mac上構建動態庫。當我在我的測試代碼上運行valgrind時,鏈接到我的動態庫,我得到一塊肯定丟失的內存。這裏是Valgrind的報告:用戶泄漏,libC++泄漏或誤報

==45659== 36 bytes in 1 blocks are definitely lost in loss record 57 of 228 
==45659== at 0x66BB: malloc (vg_replace_malloc.c:300) 
==45659== by 0x31EAB0: __Balloc_D2A (in /usr/lib/system/libsystem_c.dylib) 
==45659== by 0x31F2A5: __d2b_D2A (in /usr/lib/system/libsystem_c.dylib) 
==45659== by 0x31BED6: __dtoa (in /usr/lib/system/libsystem_c.dylib) 
==45659== by 0x3438A9: __vfprintf (in /usr/lib/system/libsystem_c.dylib) 
==45659== by 0x36A2DA: __v2printf (in /usr/lib/system/libsystem_c.dylib) 
==45659== by 0x34FF66: _vsnprintf (in /usr/lib/system/libsystem_c.dylib) 
==45659== by 0x34FFC5: vsnprintf_l (in /usr/lib/system/libsystem_c.dylib) 
==45659== by 0x34057A: snprintf_l (in /usr/lib/system/libsystem_c.dylib) 
==45659== by 0x10C75A: std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::do_put(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, char, double) const (in /usr/lib/libc++.1.dylib) 
==45659== by 0xF3221: std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(double) (in /usr/lib/libc++.1.dylib) 
==45659== by 0x12102: lmpsdata::header_data::write_dimension(std::__1::basic_ofstream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) (header_data.cpp:75) 
==45659== 
==45659== LEAK SUMMARY: 
==45659== definitely lost: 36 bytes in 1 blocks 
==45659== indirectly lost: 0 bytes in 0 blocks 
==45659==  possibly lost: 0 bytes in 0 blocks 
==45659== still reachable: 18,340 bytes in 215 blocks 
==45659==   suppressed: 25,274 bytes in 374 blocks 

這特定的代碼段不涉及我是動態分配的任何內存,只有STL對象和流使用。我已經將頭文件和valgrind報告的方法連接起來導致泄漏。有人能解釋一下這裏發生了什麼嗎?我感到非常困惑。如果需要了解更多信息,請讓我知道

header_data.h

#ifndef ____header_data__ 
#define ____header_data__ 

#include <string> 
#include <fstream> 
#include <cstdint> 
#include <vector> 
#include <map> 

namespace lmpsdata { 
class header_data 
{//LAMMPS header information 
    //only the point particle header information has been implemented 
    //since the current atom base class is designed for point particles only 
public: 
    header_data():xdim(2), ydim(2), zdim(2), tiltdim(3) {} 
    //methods 
    void read(const std::string &, const std::string &); 
    void write(std::ofstream &, const std::string &); //this write command will replace the one 
    std::string check_header_keyword(const std::string &, bool &); 
    uint64_t get(const std::string&); 
    std::vector<double>& get_vector(const std::string&); 
    void set(const std::string&, uint64_t); 
    void set_vector(const std::string&, std::vector<double>&); 

private: 
    //methods 
    void read_dimension(const std::string&, const std::string&); 
    void write_dimension(std::ofstream&, const std::string&); 

    //members 
    uint64_t atomnum; 
    uint64_t bondnum; 
    uint64_t anglenum; 
    uint64_t dihedralnum; 
    uint64_t impropernum; 
    uint64_t atomtypenum; 
    uint64_t bondtypenum; 
    uint64_t angletypenum; 
    uint64_t dihedraltypenum; 
    uint64_t impropertypenum; 
    uint64_t extrabondnum; 

    std::vector<double> xdim; 
    std::vector<double> ydim; 
    std::vector<double> zdim; 
    std::vector<double> tiltdim;//for use with triclinic system 

    std::map<std::string, uint64_t&> int_map { 
     {"atoms", atomnum}, 
     {"bonds", bondnum}, 
     {"angles", anglenum}, 
     {"dihedrals", dihedralnum}, 
     {"impropers", impropernum}, 
     {"atom types", atomtypenum}, 
     {"bond types", bondtypenum}, 
     {"angle types", angletypenum}, 
     {"dihedral types", dihedraltypenum}, 
     {"improper types", impropertypenum}, 
     {"extra bond per atom", extrabondnum}, 
    }; 
    std::map<std::string, std::vector<double>&> v_map { 
     {"xlo xhi", xdim}, 
     {"ylo yhi", ydim}, 
     {"zlo zhi", zdim}, 
     {"xy xz yz", tiltdim} 
    }; 
}; 
} 
#endif /* defined(____header_data__) */ 

lmpsdata.cpp僅write_dimension方法和文件的開頭顯示

#include "header_data.h" 
#include <stdexcept> 
using namespace lmpsdata; 
void header_data::write_dimension(std::ofstream &file, const std::string& keyword) 
{ 
    std::vector<double>& data = v_map.at(keyword); 
    for (auto value: data) { 
     file << value << " "; 
    } 
} 

+0

您是否已確認您傳入'header_data :: write_dimension()'的流正確關閉並在事後刪除?另外,你是否嘗試將語句'file << value <<「」;'分解爲多個語句和行,以查明問題是否與ofstream或格式化命令相關?另外,您是否使用最近的Valgrind版本? – oliver 2015-04-07 14:00:02

+0

上面的valgrind報告發生在ostream關閉和左側打開的情況下。我第一次跑valgrind,我忘了關閉流,我認爲這是問題。但問題仍然存在。 – 2015-04-21 16:24:56

+0

我正在使用valgrind-3.10.1。稍後我會檢查格式。 – 2015-04-21 16:50:34

回答

1

你還沒有提到你正在使用的OSX和valgrind的確切版本。我一直無法完全重現我使用的版本(OSX 10.10; valgrind HEAD == Valgrind-3.11.0.SVN)。

這不是在C++標準庫中,而是在C庫中。您應該能夠重現它(幾乎相同)用簡單的代碼:

#include <stdio.h> 
#include <xlocale.h> 

int 
main(int argc, char **argv) 
{ 
    locale_t loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); 
    double d = 22.22; 
    char buffer[1024]; 
    snprintf_l(buffer, 1024, loc, "%f\n", d); 
    printf("%s", buffer); 
    freelocale(loc); 
} 

valgrind --show-leak-kinds=all --leak-check=full ./leak運行我看到一些「仍可達」泄漏(你應該表現在這種情況下,實際泄漏):

==26151== 32 bytes in 1 blocks are still reachable in loss record 28 of 85 
==26151== at 0x10000850B: malloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so) 
==26151== by 0x1002BC7DF: __Balloc_D2A (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002B9533: __rv_alloc_D2A (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002B9B3A: __dtoa (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002E1D52: __vfprintf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x10030A9AE: __v2printf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002EF154: _vsnprintf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002EF1B3: vsnprintf_l (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002DF5F7: snprintf_l (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x100000ECA: main (leak.cpp:10) 
==26151== 
==26151== 36 bytes in 1 blocks are still reachable in loss record 30 of 85 
==26151== at 0x10000850B: malloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so) 
==26151== by 0x1002BC7DF: __Balloc_D2A (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002BD055: __d2b_D2A (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002B986B: __dtoa (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002E1D52: __vfprintf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x10030A9AE: __v2printf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002EF154: _vsnprintf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002EF1B3: vsnprintf_l (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002DF5F7: snprintf_l (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x100000ECA: main (leak.cpp:10) 
==26151== 
==26151== 80 bytes in 1 blocks are still reachable in loss record 47 of 85 
==26151== at 0x10000850B: malloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so) 
==26151== by 0x1002BC736: __Balloc_D2A (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002BD055: __d2b_D2A (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002B986B: __dtoa (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002E1D52: __vfprintf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x10030A9AE: __v2printf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002EF154: _vsnprintf (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002EF1B3: vsnprintf_l (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x1002DF5F7: snprintf_l (in /usr/lib/system/libsystem_c.dylib) 
==26151== by 0x100000ECA: main (leak.cpp:10) 

我會對它進行抑制,因爲它幾乎毫無疑問不是真正的泄漏,完全不受你的控制。

看着已發佈的OSX libc source,我看不到錯誤出現在哪裏 - 320和後來的所有看起來都不錯;底層代碼似乎在必要時分配和釋放。但是,這個錯誤可能已經被引入並修復,因爲我沒有對所有來源進行詳盡的拖網。有問題的文件是vfprintf.c,您正在查看dtoaresult作業&空閒。

要確定您的libc的版本,你可以這樣做:

$ otool -l /usr/lib/system/libsystem_c.dylib | grep -A5 ID_ 

在我的系統我得到的輸出:

  cmd LC_ID_DYLIB 
     cmdsize 64 
     name /usr/lib/system/libsystem_c.dylib (offset 24) 
    time stamp 1 Thu Jan 1 01:00:01 1970 
     current version 1044.10.1 
compatibility version 1.0.0 

997,我想,是小牛隊(10.9)。我不知道他們是否在特拉維斯時間框架的某一時刻在代碼中引入了泄漏,然後對其進行了修復 - 在__vfprintf例程中似乎沒有代碼路徑,這些代碼路徑實際上在任何已發佈的源代碼中都有泄漏。

+0

我在小牛(10.9)中,libsystem_c.dylib的版本是997.90.3。當我在valgrind中運行代碼時,我沒有發現任何明顯的泄漏,只有4個仍然可以訪問,它們與你的一樣。我認爲你的權利可能不是真正的泄漏。我想知道這是否是valgrind-3.10.1和C++ 11的問題。 – 2015-04-21 16:49:17

+0

valgrind 3.10.1誤報漏洞很容易造成問題,因爲它無法正確跟蹤分配情況 - 我已經看到了其中的一部分,通常系統級別的壓縮文件用於防止報告這些泄漏。 – Petesh 2015-04-21 17:56:09

+0

謝謝我將研究如何設置一個壓縮文件。 – 2015-04-29 00:13:51