【问题标题】:gdb not printing string value correctlygdb 没有正确打印字符串值
【发布时间】:2011-03-02 17:19:18
【问题描述】:

我有一个多线程 (pthreads) 程序,其中 main() 调用函数 omp_file_open_all() 并将字符串作为 char* 与其他参数一起传递。我正在使用 gdb 调试一些东西,发现 gdb 没有正确打印出字符串值,而函数内部的 printf 可以正确打印出它。

Breakpoint 1, omp_file_open_all (fd=0x423bb950, filename=0x7f605df078e0 "", mode=-16843009) at pthread_coll_file_open.c:29
29          if(omp_get_thread_num() == MASTER)
(gdb) print filename
$1 = 0x7f605df078e0 ""

所以 gdb 将 filename 显示为空,而函数内的 printf 将正确的值输出为“/tmp/test.out”。被调用的函数 (omp_file_open_all) 定义如下(与 main() 不在同一个文件中): int omp_file_open_all (int fd, char* filename, int mode);

我不能在这里发布我的程序,因为这是一个更大的代码的一部分。 1500 行代码。 'filename' 是一个全局变量,在新线程产生之前由主线程在 main() 中设置。

所以这不是错误,我只是偶然发现它,但我有兴趣找出 gdb 不显示正确值的原因。

操作系统:64 位 OpenSUSE, gdb 6.8

感谢您的帮助。

【问题讨论】:

  • 没有人希望你发布你的整个 1.5KLOC 程序;做一个测试用例!
  • 0x7f605df078e0 是一个非常可疑的指针值。没有任何代码,我们无法说出原因。
  • 当您使用printf 和使用gdb 进行测试时,您的编译是否有所不同?也许编译器正在优化文件名...
  • @pmg,我不使用 printf 和 gdb 单独测试。 printf 始终存在。
  • @Tomalak,我尝试剥离 1.5KLOC 代码,但无法重现上述情况。我编写了类似的单独测试用例,但没有看到上述行为。 gdb 正确显示文件名。并且原谅我之前没有说这个,但是上面的代码是pthreads代码。

标签: c gdb pthreads


【解决方案1】:

您的代码中可能有问题。使用以下代码 sn-p,我得到了 gdb 正确打印的字符串。

#include <stdio.h>
#include <stdlib.h>

void checkString( char* fileName )
{
    printf("%s", fileName);
}

int main()
{
    char* name = "temp";
    checkString(name);

    return 0;
}


mahesh-babu-vattiguntas-macbook-pro:Desktop mahesh$ gdb gdb.out
GNU gdb 6.3.50-20050815 (Apple version gdb-1469) (Wed May  5 04:36:56 UTC 2010)
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 "x86_64-apple-darwin"...Reading symbols for shared libraries .. done

(gdb) b gdb.c:6
Breakpoint 1 at 0x100000ebc: file gdb.c, line 6.
(gdb) run gdb.out
Starting program: /Users/mahesh/Desktop/gdb.out gdb.out
Reading symbols for shared libraries +. done

Breakpoint 1, checkString (fileName=0x100000f05 "temp") at gdb.c:6
6       printf("%s", fileName);
(gdb) p fileName
$1 = 0x100000f05 "temp"
(gdb) 

【讨论】:

    【解决方案2】:

    在你命中断点后尝试前进一行(gdb "s" 命令),然后再次尝试打印。我有时会看到 gdb 在函数开头中断时无法正确显示参数值。

    【讨论】:

      【解决方案3】:

      我的第一个猜测是存在范围问题,因为函数参数的名称和您的全局变量是相同的。但是,对于以下非常小的程序,情况似乎并非如此:

      #include <cstdio>
      
      static char const* filename = "something";
      
      int foobar(char const* filename)
      {
        printf("%s\n", filename);
      }
      
      int main(int argc, char** argv)
      {
        return foobar("somethingelse");
      }
      

      编译:

      g++ -ggdb -g3 -O0    test.cpp   -o test
      

      GDB(7.2,也在 x64 但 Ubuntu 上)提供:

      Breakpoint 1, foobar (filename=0x400706 "somethingelse") at test.cpp:7
      7         printf("%s\n", filename);
      (gdb) p filename
      $1 = 0x400706 "somethingelse"
      

      因此,这与范围本身无关。此外,输出表明该参数在执行时确实是一个空字符串。您能否在闯入调试器的同时向我们提供bt 的输出?最后两个堆栈帧就足够了。

      【讨论】:

      • @Kshitij_Mehta:抱歉,什么都看不到。你能把它编辑成你原来的问题吗?还是说没有输出?
      • 这是 bt 的输出:(gdb) bt #0 omp_file_open_all (fd=0x41d90950, filename=0x7fe348e858e0 "", mode=1223186656) at pthread_coll_file_open.c:46 #1 0x0000000000401a81 intthread_task 1) 在 main.c:177 #2 0x00000000004019ca in pthread_start_routine (threadid=0x60a100) at main.c:155 #3 0x00007fe348e7c040 in start_thread () from /lib64/libpthread.so.0 #4 0x00007fe348bef0cd in clone () from /lib64 /libc.so.6
      • 如果我只运行一个线程,文件名会有所不同。以下是 gdb 的输出:'Breakpoint 1, omp_file_open_all (fd=0x405b70, filename=0x401520 "1▒I\211▒^H\211▒H\203▒▒PTI▒▒[@", mode=1701996660) at pthread_coll_file_open.c:29 29 if(omp_get_thread_num() == MASTER) (gdb) p filename $1 = 0x401520 "1▒I\211▒^H\211▒H\203▒▒PTI▒▒[@" ' For threads>1 , 非主线程的文件名是空的
      • 是否有可能其中一个线程正在篡改全局文件名值?您使用什么存储类型作为文件名?由于您使用 OMP,您是否确保所有线程都可以访问相同的资源,或者它们最终会获得不同的副本? ...
      • 文件名是从配置文件中读取的,如下所示:'(fgets(buffer, MAXLINE, Conf_File); strncpy(tmpfilename, &buffer[i], MAXLINE-i); filename = tmpfilename;' (只是显示重要的sn-ps代码)。另外,我并没有真正使用openmp,这个库复制了一些openmp函数,它几乎是一个pthreads库
      猜你喜欢
      • 2020-07-04
      • 2011-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 2015-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多