gdb调试双重自由未被valgrind检测到(?)

时间:2010-09-12 10:47:35

标签: c++ gdb valgrind

大约每三次我运行一次程序,malloc报告一个双重自由错误; e.g。

myprogram(703,0xb06d9000) malloc: *** error for object 0x17dd0240: double free
*** set a breakpoint in malloc_error_break to debug

我通过valgrind运行了相同的代码十几次,但它从未报告过双重免费。

我通过gdb在malloc_error_break上使用断点运行代码,并且(当错误发生时)错误始终在标准c ++库函数中报告。我隔离了父函数并在测试单元中对其进行了调整但没有错误。

我认为父函数/标准c ++库不应该受到责备,它只是释放它分配的东西,但释放了父程序中的其他一些函数。

我已经尝试查找哪个对象被双重释放但我的gdb技能无法找到第一个被释放的对象。请帮助我找到哪个对象导致第一个免费,另外任何帮助,为什么我的程序生成此错误。谢谢。

父功能归结为:

int i;
double px, py;
int start, finish;
std::string comment;
std::vector<double> x, y;

std::fstream myfile;
myfile.open("filename.txt", std::ios_base::in);

// Read header

std::getline(myfile, comment);

// Read data

while(!myfile.eof())
{
  myfile >> comment >> start >> comment >> finish;

  for(i = 0; i <= finish-start; i++)
  {
    myfile >> px >> py;  // double free here

    x.push_back(px);
    y.push_back(py);
  }
}

编辑: 我的数据文件是这样的:

Comment: My Data
start 33 end 36
10.2 139.0076
9.22616 141.584
8.62802 141.083
8.87098 141.813
start 33 end 35
300.354 405
301.698 404.029
303.369 403.953
start 33 end 35
336.201 148.07
334.616 147.243
334.735 146.09

gdb的回溯是

(gdb) backtrace
#0  0x93c2d4a9 in malloc_error_break ()
#1  0x93c28497 in szone_error ()
#2  0x93b52503 in szone_free ()
#3  0x93b5236d in free ()
#4  0x93b51f24 in localeconv_l ()
#5  0x93c18163 in strtod_l$UNIX2003 ()
#6  0x93c192e0 in strtod$UNIX2003 ()
#7  0x919b76e8 in std::__convert_to_v<double> ()
#8  0x919983cf in std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::do_get ()
#9  0x91991671 in std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::get ()
#10 0x9198d2dc in std::istream::operator>> ()

重申一点,我需要帮助才能找到第一次释放的对象,我对重构这个函数的代码并不感兴趣 - 我不认为这会引起问题;除非你能在其中找到灾难性的东西。

编辑:更改了示例代码。

5 个答案:

答案 0 :(得分:4)

您似乎正在使用Mac OSX(您应该泄露这一事实: - )

several environment variables可以帮助您调试堆损坏。

特别是MallocStackLoggingNoCompact看起来很有希望。

以下是我看到的内容:

$ cat t.c
int main()
{
  char *p = strdup("hello");
  free(p);
  free(p);
  return 0;
}

$ gdb ./a.out
GNU gdb 6.3.50-20050815 (Apple version gdb-967) (Tue Jul 14 02:11:58 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin"...Reading symbols for shared libraries ... done

(gdb) set env MallocStackLoggingNoCompact 1
(gdb) b malloc_error_break
Breakpoint 1 at 0x13f44a9
(gdb) r
Starting program: /Users/emp-russian/a.out 
bash(22634) malloc: recording malloc stacks to disk using standard recorder
bash(22634) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly
bash(22634) malloc: process 22536 no longer exists, stack logs deleted from /tmp/stack-logs.22536.a.out.8D3VZO
bash(22634) malloc: stack logs being written into /tmp/stack-logs.22634.bash.kjFTGa
arch(22634) malloc: recording malloc stacks to disk using standard recorder
arch(22634) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly
arch(22634) malloc: stack logs deleted from /tmp/stack-logs.22634.bash.kjFTGa
arch(22634) malloc: stack logs being written into /tmp/stack-logs.22634.arch.8L8iLX
Reading symbols for shared libraries ++. done
Breakpoint 1 at 0x909b54a9
a.out(22634) malloc: recording malloc stacks to disk using standard recorder
a.out(22634) malloc: stack logging compaction turned off; size of log files on disk can increase rapidly
a.out(22634) malloc: stack logs deleted from /tmp/stack-logs.22634.arch.8L8iLX
a.out(22634) malloc: stack logs being written into /tmp/stack-logs.22634.a.out.s1qQRw
a.out(22634) malloc: *** error for object 0x100080: double free
*** set a breakpoint in malloc_error_break to debug

Breakpoint 1, 0x909b54a9 in malloc_error_break ()
(gdb) shell ls -l /tmp/stack-logs.22634.a.out.s1qQRw
total 16
-rw-------  1 emp-russian  wheel   96 Sep 12 09:42 stack-logs.index
-rw-------  1 emp-russian  wheel  208 Sep 12 09:42 stack-logs.stacks

(gdb) shell malloc_history 22634 0x100080

我们实际上并不关心历史的第一部分:

Call [2] [arg=24]: thread_a0103720 |_dyld_start | dyldbootstrap::start(mach_header const*, int, char const**, long) | dyld::_main(mach_header const*, unsigned long, int, char const**, char const**, char const**) | dyld::initializeMainExecutable() | ImageLoader::runInitializers(ImageLoader::LinkContext const&) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) | libSystem_initializer | __keymgr_initializer | _dyld_register_func_for_add_image | dyld::registerAddCallback(void (*)(mach_header const*, long)) | dwarf2_unwind_dyld_add_image_hook | calloc | _malloc_initialize | malloc_set_zone_name | malloc_zone_malloc | __disk_stack_logging_log_stack | reap_orphaned_log_files | opendir$INODE64$UNIX2003 | __opendir2$INODE64$UNIX2003 | telldir$INODE64$UNIX2003 | malloc | malloc_zone_malloc 
Call [4] [arg=0]: thread_a0103720 |_dyld_start | dyldbootstrap::start(mach_header const*, int, char const**, long) | dyld::_main(mach_header const*, unsigned long, int, char const**, char const**, char const**) | dyld::initializeMainExecutable() | ImageLoader::runInitializers(ImageLoader::LinkContext const&) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) | ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) | libSystem_initializer | __keymgr_initializer | _dyld_register_func_for_add_image | dyld::registerAddCallback(void (*)(mach_header const*, long)) | dwarf2_unwind_dyld_add_image_hook | calloc | _malloc_initialize | malloc_set_zone_name | malloc_zone_malloc | __disk_stack_logging_log_stack | reap_orphaned_log_files | closedir$UNIX2003 | _reclaim_telldir | free | malloc_zone_free

但这是有趣的东西:

Call [2] [arg=6]: thread_a0103720 |0x1 | start | main | strdup | malloc | malloc_zone_malloc 
Call [4] [arg=0]: thread_a0103720 |0x1 | start | main | free | malloc_zone_free 
Call [4] [arg=0]: thread_a0103720 |0x1 | start | main | free | malloc_zone_free 

答案 1 :(得分:2)

我目前正试图在MacOS上追踪“试图释放未分配的指针”错误。我的错误是由程序中的五十分之一(具有相同的输入)触发的,当然,当我运行调试器(叹气)时,它从未发生过。

我在下面描述的是在触发错误的罕见情况下获得回溯的便捷方式,而无需在每次运行时与gdb交互。它是EmployedRussian的优秀提示的替代品。

使用以下gdb命令文件:

# malloc_error_break.gdb
break malloc_error_break
run         # Add program arguments here
backtrace

运行gdb,执行命令文件,如下所示:

gdb -x malloc_error_break.gdb --batch my_program

如果程序在没有遇到释放问题的情况下运行,它将打印“No stack”以响应backtrace命令,然后gdb将退出(感谢--batch选项)。

如果程序遇到释放错误,我会(希望!)在gdb退出之前得到一个堆栈。

答案 2 :(得分:1)

这一行:

myfile >> comment

只会读取“评论:”而不是整行“评论:我的数据”。在该行之后从myfile读取的下一个内容将是“我的”,这可能会导致问题。

特别是,第一次通过外部循环,它将尝试将字符串“Data”读入start,并且将无法执行此操作(因为它无法解析为整数) 。所以声明:

myfile >> comment >> start >> comment >> finish;

将中止,startfinish都将保持未初始化状态。

根据startfinish的(任意)未初始化值,这可以轻松地使您的内循环无限。将无限数量的元素插入向量中可能会导致奇怪的行为,虽然我没有看到你做的崩溃...它只是运行了很长时间而且因为我没有耐心而杀了它。

但是,当我通过从第一行删除“我的数据”来解决此错误时,我可以运行您的程序10,000次而不会崩溃。

答案 3 :(得分:0)

尝试运行gdb,cont到崩溃点,然后打印回溯(类型bt);看看是否有助于指出问题所在(注意,你必须在调试模式下编译程序,g ++ -g,打印清晰的回溯)。

编辑: 在大多数机器上,当你释放/删除一个内存位置时,你正在释放的指针不是空的。在您第二次释放内存时,请尝试添加“= NULL”,即:

delete myPointer;
myPointer = NULL;

不能解决问题;但是,它将隔离第一个free()/ delete也是完全相同的行的可能性(但是在之前的执行中,例如,如果你在循环中)。

顺便说一下,你的代码片段不包含任何动态分配的内存(除了std :: string,内部动态分配内存)。

答案 4 :(得分:0)

您是否了解了开始和结束的值以及文件是否有足够的内容来填充向量x和y?

更好的方法是重新考虑循环逻辑 - 你应该打破你点击文件EOF的那一刻。在这一点上,你已经把它留给了信仰。