【问题标题】:GDB doesn't let me read argv memory segmentGDB 不允许我读取 argv 内存段
【发布时间】:2019-01-14 10:38:00
【问题描述】:

我有这个用 C 语言编写的简单脚本:

#include <stdio.h>

void usage(char *program_name) {
   printf("Usage: %s <message> <# of times to repeat>\n", program_name);
   exit(1);
}

int main(int argc, char *argv[]) {
   int i, count;

//  if(argc < 3)      // If less than 3 arguments are used,
//    usage(argv[0]); // display usage message and exit.

   count = atoi(argv[2]); // convert the 2nd arg into an integer
   printf("Repeating %d times..\n", count);

   for(i=0; i < count; i++)
      printf("%3d - %s\n", i, argv[1]); // print the 1st arg
}

我正在用 GDB 做一些测试。

我这样做了:

(gdb) run test
Starting program: /home/user/Desktop/booksrc/convert2 test

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6

显然它会出现分段错误,因为程序需要三个 argv 才能工作。我评论了控制的行。所以它出错了。

(gdb) where
#0  0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6
#1  0x00007ffff7a53a80 in atoi () from /usr/lib/libc.so.6
#2  0x00005555555546ea in main (argc=2, argv=0x7fffffffe958) at convert2.c:14
(gdb) break main
Breakpoint 1 at 0x5555555546d2: file convert2.c, line 14.
(gdb) run test
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/user/Desktop/booksrc/convert2 test

Breakpoint 1, main (argc=2, argv=0x7fffffffe958) at convert2.c:14
14     count = atoi(argv[2]); // convert the 2nd arg into an integer
(gdb) cont
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6
(gdb) x/3xw 0x7fffffffe958 // this is memory of the "argv" some line before
0x7fffffffe958: 0xffffebfe  0x00007fff  0xffffec22
(gdb) x/s 0xffffebfe
0xffffebfe: <error: Cannot access memory at address 0xffffebfe>
(gdb) x/s 0x00007fff
0x7fff: <error: Cannot access memory at address 0x7fff>
(gdb) x/s 0xffffec22
0xffffec22: <error: Cannot access memory at address 0xffffec22>

理论上,使用“x/s”,我应该在第一个地址中看到命令行,在第二个地址中看到“test”,在第三个地址中看到 null。但什么都没有。如果我将该地址复制粘贴到 ascii 到字符串转换器,它会给我没有任何意义的数据。我做错了什么?

【问题讨论】:

  • 你确定你设置了命令行参数吗?经常检查。
  • 我该怎么办?我是 C 新手
  • 取消注释代码中的检查。您评论它可能是因为它不允许您继续。您需要设置命令行选项,并且 argc 必须3
  • nono 我评论它只是为了用gdb检查,只是为了练习。我是故意的
  • 为什么?按照我的回答在 gdb 中设置参数。如果你不得不评论它 - 你的 gdb 调试是错误的,因为你没有设置命令行参数

标签: c memory segmentation-fault gdb argv


【解决方案1】:

您的平台使用 64 位指针,因此请尝试:

(gdb) x/3xg 0x7fffffffe958

显示argv数组中的64位指针,然后:

(gdb) x/s 0x00007fffffffebfe

或者只是:

(gdb) p argv[0]

【讨论】:

  • 有效!!谢谢!但是为什么 0x00007fff 给我 null 而它应该是第三个 argv(0xffffec22,即“测试”,应该是第二个地址(即 null)。我不必考虑地址的顺序argv 的位置?
  • @AllExJ : 0x00007fff 不是有效地址 - 它是地址的最重要的一半。要获取 argv 数组中的第二个字符串,您需要完整地址:0x7fffffffec22。或者只是让你的生活变得轻松,然后p argv[1]
  • 另外,将内存地址复制到十六进制到文本站点并转换它们是错误的吗?
  • @AllExJ :这些十六进制值是内存地址。它们代表字符串的位置不是字符串本身。您需要检查 (x) 该位置的内存,并将其解释为如上所示的字符串,以显示该字符串。所以,不:将地址转换为文本不会给你字符串。
  • @AllExJ :要使argv 符号可用,在到达您设置的断点后跳出一步(您在main 符号上设置断点,而不是main 的开头函数)。
【解决方案2】:

首先总是检查命令行是否正确

从您的代码中取消注释检查。

然后在gdb 中设置参数(在运行之前)

(gdb) set args "hello world" 12

【讨论】:

    猜你喜欢
    • 2019-01-18
    • 1970-01-01
    • 2021-06-17
    • 2023-03-14
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多