用户泄漏,libc ++泄露或假阳性 [英] User Leak, libc++ leak or false positive

查看:186
本文介绍了用户泄漏,libc ++泄露或假阳性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用clang编译器和libc ++标准库在C ++ 11中构建一个动态库。当我运行valgrind在我的测试代码链接到我的动态库,我得到一个内存块肯定是丢失。这里是valgrind报告:

  == 45659 == 1个块中的36个字节绝对会丢失在损失记录中57个228 
== 45659 == at 0x66BB:malloc(vg_replace_malloc.c:300)
== 45659 == by 0x31EAB0:__Balloc_D2A(在/usr/lib/system/libsystem_c.dylib中)
= = 45659 == by 0x31F2A5:__d2b_D2A(在/usr/lib/system/libsystem_c.dylib)
== 45659 == by 0x31BED6:__dtoa(在/usr/lib/system/libsystem_c.dylib)
== 45659 == by 0x3438A9:__vfprintf(在/usr/lib/system/libsystem_c.dylib)
== 45659 == by 0x36A2DA:__v2printf(在/usr/lib/system/libsystem_c.dylib)
== 45659 == by 0x34FF66:_vsnprintf(在/usr/lib/system/libsystem_c.dylib)
== 45659 == by 0x34FFC5:vsnprintf_l(在/usr/lib/system/libsystem_c.dylib )
== 45659 == by 0x34057A:snprintf_l(在/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(在/ usr / 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> &)(header_data.cpp:75)
== 45659 ==
== 45659 == LEAK摘要:
== 45659 ==明确丢失:1个块中36个字节
== 45659 ==间接丢失:0个字节在0块
== 45659 ==可能丢失:0个字节在0块
== 45659 ==仍然可达:18,340字节在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头信息
//只有点粒子头信息已实现
//因为当前原子基类只为点粒子设计
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&); //这个写命令将替换一个
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:
//方法
void read_dimension(const std :: string& const std :: string&
void write_dimension(std :: ofstream& const; std :: string&);

//成员
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; //用于三元系统

std :: map< std :: string,uint64_t&> int_map {
{atoms,atomnum},
{bonds,bondnum},
{angles,anglenum},
{dihedrals,dihedralnum}
{impropers,impropernum},
{atom types,atomtypenum},
{bond types,bondtypenum} ,
{二面体类型,二面体型},
{不适当类型,不当类型},
{每个原子的额外键,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方法和文件开头显示

  #includeheader_data.h
#include< stdexcept> ;
使用命名空间lmpsdata;
void header_data :: write_dimension(std :: ofstream& file,const std :: string& keyword)
{
std :: vector< double> data = v_map.at(关键字);
for(auto value:data){
file<<值<< ;
}
}

如果需要更多信息,请让我知道。 / p>

解决方案

你没有提到你使用的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 \\\
,d);
printf(%s,buffer);
freelocale(loc);
}

使用运行时valgrind --show-leak- types = all --leak-check = full ./leak 我看到一些仍然可达的泄漏(在这种情况下你应该显示实际泄漏):



pre> == 26151 == 1个块中的32个字节在丢失记录中仍然可达28
== 26151 == at 0x10000850B:malloc(在/ usr / local / Cellar / valgrind / HEAD / lib / valgrind / vgpreload_memcheck-amd64-darwin.so)
== 26151 == by 0x1002BC7DF:__Balloc_D2A(在/usr/lib/system/libsystem_c.dylib中)
== 26151 == by 0x1002B9533:__rv_alloc_D2A(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002B9B3A:__dtoa(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002E1D52:__vfprintf(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x10030A9AE:__v2printf(在/usr/lib/system/libsystem_c.dylib中)
== 26151 == by 0x1002EF154:_vsnprintf(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002EF1B3:vsnprintf_l(在/ usr / lib / system / libsystem_c。 dylib)
== 26151 == by 0x1002DF5F7:snprintf_l(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x100000ECA:main(leak.cpp:10)
== 26151 ==
== 26151 == 1个块中的36个字节在丢失记录中仍然可达30 of 85
== 26151 == at 0x10000850B:malloc(在/ usr / local / Cellar / valgrind / HEAD / lib / valgrind / vgpreload_memcheck-amd64-darwin.so)
== 26151 == by 0x1002BC7DF:__Balloc_D2A(在/usr/lib/system/libsystem_c.dylib中)
== 26151 == by 0x1002BD055:__d2b_D2A(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002B986B:__dtoa(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002E1D52:__vfprintf(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x10030A9AE:__v2printf(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002EF154:_vsnprintf(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002EF1B3:vsnprintf_l(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002DF5F7:snprintf_l(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x100000ECA:main(leak.cpp:10)
== 26151 ==
== 26151 == 1个块中的80个字节在丢失记录中仍然是可达的85
== 26151 == at 0x10000850B:malloc(在/ usr / local / Cellar / valgrind / HEAD / lib / valgrind / vgpreload_memcheck-amd64-darwin.so)
== 26151 == by 0x1002BC736:__Balloc_D2A(在/usr/lib/system/libsystem_c.dylib中)
== 26151 = = by 0x1002BD055:__d2b_D2A(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002B986B:__dtoa(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002E1D52:__vfprintf(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x10030A9AE:__v2printf(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002EF154:_vsnprintf(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002EF1B3:vsnprintf_l(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x1002DF5F7:snprintf_l(在/usr/lib/system/libsystem_c.dylib)
== 26151 == by 0x100000ECA:main(leak.cpp:10)

我会给它一个抑制,因为它几乎不可能是一个真正的泄漏,完全不受你的控制。 / p>

查看已发布的 OSX libc源,我不能看到错误存在的地方 - 320和以后所有看起来OK;其中基本代码似乎在必要时分配和释放。该bug可能已经引入和修复,虽然,因为我没有执行穷尽拖网所有的来源;相关文件是 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)
时间戳1 Thu Jan 1 01:00:01 1970
当前版本1044.10.1
兼容版本1.0.0

997,我想,是小牛(10.9)。我不知道他们是否在代码中引入一个泄漏在特定时间框架的某一点,然后修复它 - 似乎没有一个代码路径在 __ vfprintf 例程,其实在任何已发布的源中泄漏。


I am building a dynamic library on mac in C++11 using the clang compiler and libc++ standard library. When I run valgrind on my test code which links to my dynamic library I get one block of memory that is definitely lost. Here is the valgrind report:

==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

That particular section of code does not deal with any memory I have dynamically allocated, only STL objects and streams are used. I have attached both the header file and the method reported by valgrind as causing the leak. Can someone please explain what is going on here? I am absolutely baffled.

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 only write_dimension method and beginning of file is shown

#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 <<  " ";
    }
}

If more information is needed please let me know.

解决方案

You have not mentioned the exact versions of OSX and valgrind that you're using. I've not been able to entirely reproduce this on the version that I'm using (OSX 10.10; valgrind HEAD==Valgrind-3.11.0.SVN).

This is not in the C++ standard library, but in the C library. You should be able to reproduce it (almost identically) with the simple code:

#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);
}

When run with valgrind --show-leak-kinds=all --leak-check=full ./leak I see some 'still reachable' leaks (yours should show actual leaks in this case):

==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)

I'd put in a suppression for it, as it's almost undoubtably not a real leak and is completely out of your control.

looking at the published OSX libc source, I can't see where the bug is present - 320 and later all look OK; with the underlying code appearing to allocate and free where necessary. The bug may have been introduced and fixed, though, as I didn't perform an exhaustive trawl of all the sources; the file in question is vfprintf.c, you're looking at the dtoaresult assignments & frees.

To determine your version of libc, you can do:

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

On my system I get the output:

          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, I think, is mavericks (10.9). I don't know if they introduced a leak in the code at some point in the mavericks timeframe and then fixed it - there doesn't appear to be a code path in the __vfprintf routine that actually leaks in any of the published source.

这篇关于用户泄漏,libc ++泄露或假阳性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆