c – 最小程序在g上产生Valgrind警告,但不产生clang或VS.
发布时间:2020-12-16 07:08:46 所属栏目:百科 来源:网络整理
导读:我一直在疯狂追踪中型项目中的内存错误.我将一个最小化到下面的代码,并验证这导致Valgrind警告在注释行号处无效读取.我正在使用g 4.8.2(Debian 4.8.2-16)进行项目,使用-std = c 11 -O0进行编译. g 4.7.0也产生错误,4.4.6略微修改版本(删除C 11). clang不会导
我一直在疯狂追踪中型项目中的内存错误.我将一个最小化到下面的代码,并验证这导致Valgrind警告在注释行号处无效读取.我正在使用g 4.8.2(Debian 4.8.2-16)进行项目,使用-std = c 11 -O0进行编译. g 4.7.0也产生错误,4.4.6略微修改版本(删除C 11). clang不会导致错误,VS2013也不会.
我的问题是: >我是否在不知不觉中从事未定义的行为? 这段代码相当脆弱 – 特别是,让foo通过引用获取coord消除了这个问题,就像为Coord选择更大的类型一样,它的内存大小超过8个字节. // Types are a little strange because I wanted the minimal failing // case -- eg,row/col used to be ints. #include <cassert> #include <iostream> #include <vector> class Coord { public: bool row,col,layer; }; void foo(Coord wtf) { } std::vector<Coord> baz() { std::vector<Coord> bees; for (int i = 0; i < 4; ++i) { bees.push_back({1,1,1}); } return bees; } int main(int argc,char** argv) { auto vec = baz(); assert(vec.size() > 3); Coord bbb = vec[3]; foo(bbb); static int i = 0; foo(vec.at(3)); // Causes Valgrind warning. Coord& ccc = vec[3]; foo(ccc); // causes Valgrind warning } Valgrind输出: ==17700== Memcheck,a memory error detector ==17700== Copyright (C) 2002-2013,and GNU GPL'd,by Julian Seward et al. ==17700== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info ==17700== Command: ./a.out ==17700== ==17700== Invalid read of size 8 ==17700== at 0x400BC9: main (in /home/alexr/projects/suncatcher/a.out) ==17700== Address 0x59f80e9 is 9 bytes inside a block of size 12 alloc'd ==17700== at 0x4C27A00: operator new(unsigned long) (vg_replace_malloc.c:319) ==17700== by 0x40150A: __gnu_cxx::new_allocator<Coord>::allocate(unsigned long,void const*) (in /home/alexr/projects/suncatcher/a.out) ==17700== by 0x4013A2: std::_Vector_base<Coord,std::allocator<Coord> >::_M_allocate(unsigned long) (in /home/alexr/projects/suncatcher/a.out) ==17700== by 0x401061: void std::vector<Coord,std::allocator<Coord> >::_M_emplace_back_aux<Coord>(Coord&&) (in /home/alexr/projects/suncatcher/a.out) ==17700== by 0x400F02: void std::vector<Coord,std::allocator<Coord> >::emplace_back<Coord>(Coord&&) (in /home/alexr/projects/suncatcher/a.out) ==17700== by 0x400D25: std::vector<Coord,std::allocator<Coord> >::push_back(Coord&&) (in /home/alexr/projects/suncatcher/a.out) ==17700== by 0x400B17: baz() (in /home/alexr/projects/suncatcher/a.out) ==17700== by 0x400B64: main (in /home/alexr/projects/suncatcher/a.out) ==17700== ==17700== Invalid read of size 8 ==17700== at 0x400BEA: main (in /home/alexr/projects/suncatcher/a.out) ==17700== Address 0x59f80e9 is 9 bytes inside a block of size 12 alloc'd ==17700== at 0x4C27A00: operator new(unsigned long) (vg_replace_malloc.c:319) ==17700== by 0x40150A: __gnu_cxx::new_allocator<Coord>::allocate(unsigned long,std::allocator<Coord> >::push_back(Coord&&) (in /home/alexr/projects/suncatcher/a.out) ==17700== by 0x400B17: baz() (in /home/alexr/projects/suncatcher/a.out) ==17700== by 0x400B64: main (in /home/alexr/projects/suncatcher/a.out) ==17700== ==17700== ==17700== HEAP SUMMARY: ==17700== in use at exit: 0 bytes in 0 blocks ==17700== total heap usage: 3 allocs,3 frees,21 bytes allocated ==17700== ==17700== All heap blocks were freed -- no leaks are possible ==17700== ==17700== For counts of detected and suppressed errors,rerun with: -v ==17700== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2) 解决方法
这似乎是gcc关于加载“ghost”数据以优化少数指令
https://bugs.kde.org/show_bug.cgi?id=264936的假设
我会添加一个像宏的东西 #ifdef SOMETHING_SOMETHING #define SUPRESS_VALGRIND_FALSE_POSITIVES __attribute__((__aligned__(8))) #else #define SUPRESS_VALGRIND_FALSE_POSITIVES #endif ... class Coord { public: bool row,layer; } SUPRESS_VALGRIND_FALSE_POSITIVES ; 无论性能原因如何,强制对齐可能实际上是有益的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |