c ++内存错误:free():下一个大小无效(快)

时间:2013-02-09 23:44:25

标签: c++ gdb valgrind

我在运行测试程序时收到此错误:

*** glibc detected *** /home/me/work/co/myprog/build/myprog_test: free(): invalid next size (fast): 0x00000000006d7320 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7ffff706ab96]
/home/me/work/co/myprog/build/myprog_test(_ZN9__gnu_cxx13new_allocatorIdE10deallocateEPdm+0x20)[0x47715e]
/home/me/work/co/myprog/build/myprog_test(_ZN5boost7numeric5ublas15unbounded_arrayIdSaIdEED2Ev+0x38)[0x474aea]
/home/me/work/co/myprog/build/myprog_test(_ZN5boost7numeric5ublas6vectorIdNS1_15unbounded_arrayIdSaIdEEEED2Ev+0x19)[0x473177]
/home/me/work/co/myprog/build/myprog_test(_ZN5boost7numeric5ublas13vector_assignINS1_13scalar_assignENS1_6vectorIdNS1_15unbounded_arrayIdSaIdEEEEENS1_11zero_vectorIdS6_EEEEvRT0_RKNS1_17vector_expressionIT1_EENS1_10sparse_tagE+0x2bf)[0x47b2d9]
/home/me/work/co/myprog/build/myprog_test(_ZN5boost7numeric5ublas13vector_assignINS1_13scalar_assignENS1_6vectorIdNS1_15unbounded_arrayIdSaIdEEEEENS1_11zero_vectorIdS6_EEEEvRT0_RKNS1_17vector_expressionIT1_EE+0x26)[0x4782f4]
/home/me/work/co/myprog/build/myprog_test(_ZN5boost7numeric5ublas6vectorIdNS1_15unbounded_arrayIdSaIdEEEE6assignINS1_11zero_vectorIdS4_EEEERS6_RKNS1_17vector_expressionIT_EE+0x23)[0x4771fd]
/home/me/work/co/myprog/build/myprog_test(_ZN5boost7numeric5ublas6vectorIdNS1_15unbounded_arrayIdSaIdEEEEaSINS1_11zero_vectorIdS4_EEEERS6_RKNS1_16vector_containerIT_EE+0x4e)[0x474b52]
/home/me/work/co/myprog/build/myprog_test(_ZN9DataPointC1Ev+0x101)[0x4682d7]
/home/me/work/co/myprog/build/myprog_test(_ZN16Manager13processSampleEP6Sample+0x40)[0x46a49e]
/home/me/work/co/myprog/build/myprog_test(_ZN16Manager7addDataEP6Samplei+0x108)[0x46a8b6]
/home/me/work/co/myprog/build/myprog_test(_ZN16Manager14SetLogFileDataEP6Samplei+0x90)[0x46904a]
/home/me/work/co/myprog/build/myprog_test(_ZN36MyprogTest_testGetValuesToFilter_Test8TestBodyEv+0x6b)[0x4706a5]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc+0x52)[0x49eb29]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing8internal35HandleExceptionsInMethodIfSupportedINS_4TestEvEET0_PT_MS4_FS3_vEPKc+0x45)[0x499b76]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing4Test3RunEv+0xb9)[0x487461]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing8TestInfo3RunEv+0xf6)[0x487bb8]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing8TestCase3RunEv+0xe1)[0x48815f]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing8internal12UnitTestImpl11RunAllTestsEv+0x272)[0x48ce3e]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS0_12UnitTestImplEbEET0_PT_MS4_FS3_vEPKc+0x52)[0x49ffcb]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing8internal35HandleExceptionsInMethodIfSupportedINS0_12UnitTestImplEbEET0_PT_MS4_FS3_vEPKc+0x45)[0x49aa62]
/home/me/work/co/myprog/build/myprog_test(_ZN7testing8UnitTest3RunEv+0x5e)[0x48bbee]
/home/me/work/co/myprog/build/myprog_test(main+0x3e)[0x4a8b76]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ffff700d76d]
/home/me/work/co/myprog/build/myprog_test[0x466399]
======= Memory map: ========
00400000-004d2000 r-xp 00000000 08:01 11152935                           /home/me/work/co/myprog/build/myprog_test
006d1000-006d2000 r--p 000d1000 08:01 11152935                           /home/me/work/co/myprog/build/myprog_test
006d2000-006d3000 rw-p 000d2000 08:01 11152935                           /home/me/work/co/myprog/build/myprog_test
006d3000-006f4000 rw-p 00000000 00:00 0                                  [heap]
7ffff6fec000-7ffff71a1000 r-xp 00000000 08:01 12452670                   /lib/x86_64-linux-gnu/libc-2.15.so
7ffff71a1000-7ffff73a0000 ---p 001b5000 08:01 12452670                   /lib/x86_64-linux-gnu/libc-2.15.so
7ffff73a0000-7ffff73a4000 r--p 001b4000 08:01 12452670                   /lib/x86_64-linux-gnu/libc-2.15.so
7ffff73a4000-7ffff73a6000 rw-p 001b8000 08:01 12452670                   /lib/x86_64-linux-gnu/libc-2.15.so
7ffff73a6000-7ffff73ab000 rw-p 00000000 00:00 0
7ffff73ab000-7ffff73c0000 r-xp 00000000 08:01 12455438                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff73c0000-7ffff75bf000 ---p 00015000 08:01 12455438                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff75bf000-7ffff75c0000 r--p 00014000 08:01 12455438                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff75c0000-7ffff75c1000 rw-p 00015000 08:01 12455438                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff75c1000-7ffff76bc000 r-xp 00000000 08:01 12452678                   /lib/x86_64-linux-gnu/libm-2.15.so
7ffff76bc000-7ffff78bb000 ---p 000fb000 08:01 12452678                   /lib/x86_64-linux-gnu/libm-2.15.so
7ffff78bb000-7ffff78bc000 r--p 000fa000 08:01 12452678                   /lib/x86_64-linux-gnu/libm-2.15.so
7ffff78bc000-7ffff78bd000 rw-p 000fb000 08:01 12452678                   /lib/x86_64-linux-gnu/libm-2.15.so
7ffff78bd000-7ffff799f000 r-xp 00000000 08:01 794196                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff799f000-7ffff7b9e000 ---p 000e2000 08:01 794196                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7b9e000-7ffff7ba6000 r--p 000e1000 08:01 794196                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7ba6000-7ffff7ba8000 rw-p 000e9000 08:01 794196                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7ba8000-7ffff7bbd000 rw-p 00000000 00:00 0
7ffff7bbd000-7ffff7bd5000 r-xp 00000000 08:01 12452672                   /lib/x86_64-linux-gnu/libpthread-2.15.so
7ffff7bd5000-7ffff7dd4000 ---p 00018000 08:01 12452672                   /lib/x86_64-linux-gnu/libpthread-2.15.so
7ffff7dd4000-7ffff7dd5000 r--p 00017000 08:01 12452672                   /lib/x86_64-linux-gnu/libpthread-2.15.so
7ffff7dd5000-7ffff7dd6000 rw-p 00018000 08:01 12452672                   /lib/x86_64-linux-gnu/libpthread-2.15.so
7ffff7dd6000-7ffff7dda000 rw-p 00000000 00:00 0
7ffff7dda000-7ffff7dfc000 r-xp 00000000 08:01 12452684                   /lib/x86_64-linux-gnu/ld-2.15.so
7ffff7fd6000-7ffff7fdb000 rw-p 00000000 00:00 0
7ffff7ff7000-7ffff7ffb000 rw-p 00000000 00:00 0
7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00022000 08:01 12452684                   /lib/x86_64-linux-gnu/ld-2.15.so
7ffff7ffd000-7ffff7fff000 rw-p 00023000 08:01 12452684                   /lib/x86_64-linux-gnu/ld-2.15.so
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

我通过gdb运行它,当它到达构造函数中的行时,引起它的行是间接的构造函数调用

DataPointPtr data(new DataPoint());
=>
gyro_stdev = zero_vector;

使用DataPoint和Ptr的这些定义:

typedef boost::numeric::ublas::vector<double> vector;

struct DataPoint {
  DataPoint(void);
  long timestamp;
  bool derived;

  vector accel;
  vector accel_filtered;

  vector gyro_filtered;
  vector gyro_stdev;

  vector gyro;

  vector velocity;
  vector position;
  vector orientation;

  vector gravity;
};

typedef boost::shared_ptr<DataPoint> DataPointPtr;

boost::numeric::ublas::zero_vector<double> zero_vector(3);

DataPoint::DataPoint(void) {
  derived = false;

  accel = zero_vector;
  accel_filtered = zero_vector;

  gyro_filtered = zero_vector;
  gyro_stdev = zero_vector;

  gyro = zero_vector;

  position = zero_vector;
  velocity = zero_vector;
  orientation = zero_vector;
  gravity = zero_vector;

}

我也通过valgrind运行同样的程序,我得到了一个令人难以置信的输出量,其中大部分看起来像这样,只取决于我正在使用的三角函数(sin,tan,atan2等)。

==4161== Conditional jump or move depends on uninitialised value(s)
==4161==    at 0x536CC9D: __sin_sse2 (s_sin.c:115)
==4161==    by 0x46B23C: AccelGyroManager::getGyroEstimate(long, boost::numeric::ublas::vector<double, boost::numeric::ublas::unbounded_array<double, std::allocator<double> > >, boost::numeric::ublas::vector<double, boost::numeric::ublas::unbounded_array<double, std::allocator<double> > >) (AccelGyroManager.cxx:659)
==4161==    by 0x46BD53: AccelGyroManager::deriveData(int) (AccelGyroManager.cxx:753)
==4161==    by 0x46957A: AccelGyroManager::GetEstimate(long, float*, float*, float*, float*, float*, float*) (AccelGyroManager.cxx:294)
==4161==    by 0x467150: AgmanDllTest_testDeriveInterpolatedData_Test::TestBody() (agman_test.cxx:144)
==4161==    by 0x49EB28: void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (gtest.cc:2090)
==4161==    by 0x499B75: void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (gtest.cc:2126)
==4161==    by 0x487460: testing::Test::Run() (gtest.cc:2162)
==4161==    by 0x487BB7: testing::TestInfo::Run() (gtest.cc:2338)
==4161==    by 0x48815E: testing::TestCase::Run() (gtest.cc:2445)
==4161==    by 0x48CE3D: testing::internal::UnitTestImpl::RunAllTests() (gtest.cc:4237)
==4161==    by 0x49FFCA: bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (gtest.cc:2090)
==4161==

这个问题对我来说有点混乱。我的记忆力有可能吗?这个完全相同的构造函数调用在程序中的这一点之前成功约400次。

valgrind对s_sin.c的引用也令人困惑,我无法在任何地方找到这个文件..

非常感谢任何有关观看或探讨的建议或建议。

2 个答案:

答案 0 :(得分:3)

所以我发现了我的问题。正如Mats Petersson所说,我的问题实际上是阵列溢出。事实证明,我将这个小宝石埋在我的实用程序中进行单元测试:

SampleArray createPredictableSamples(int count) {
  SampleArray samples(new Sample[100]);
  for (int i = 0; i < count; ++i) {
  ... do stuff
  }
  return samples;
}

(注意方法参数化后,大小为100的静态数组创建...)

所以请记住,测试代码也有错误!

这是我用来发现这个的方法。

当我发布我的问题时,自上次运行测试以来,我做了一些更改。运行

的输出
valgrind --tool=memcheck --leak-check=yes ./test
因此,

有点压倒性。所以我退出了大部分的更改(使用我的版本控制来保持它们可用),然后逐个将它们作为功能集逐个应用。

每次我介绍一个更改集时,我重新运行测试,并使用valgrind检查内存错误。最后,我做了一个更改(更改我的测试数组大小),产生了大量的输出。我通过搜索(如valgrind的建议)搜索了#34;写道&#34;未初始化的存储器(即缓冲区溢出)。而且,看哪,它引导我正确解决问题,行数和所有问题。

在此过程中,我还在测试代码中发现了其他几个内存泄漏。现在,我仍然需要做更多工作来清理内存泄漏的测试代码,但我至少已经摆脱了缓冲区溢出。

感谢Mats,David和vonbrand指出我正确的方向!

答案 1 :(得分:2)

你跑valgrind真棒!现在我认为我们应该解决它的问题。

如果getGyroEstimate()正在读取硬件设备,则可能是valgrind将该值视为未初始化,即使事情正确完成。如果您认为是这种情况(如果不是,甚至可能是暂时的),您可以将其添加到valgrind“suppressions”文件中(如果您使用--gen-suppressions选项,valgrind可以帮助您半自动执行此操作)。然后你不会被这个可能无害的警告分心,并且可以继续修复它可能会抱怨的其他事情(其中一些可能是你崩溃的根本原因)。