分段错误无效内存0x0

时间:2015-10-22 07:03:23

标签: c linux ubuntu memory gdb

我的结构变量指针存在问题。我刚开始使用GDB调试问题。由于分段错误,应用程序在下面的代码行上命中时停止。 ptr_var是指向结构的指针

ptr_var->page = 0;

我发现在一系列函数调用之后ptr_var被设置为无效内存0x0,这在分配值" 0"时会导致分段错误。结构成员"页面"。函数调用系列没有对ptr_var的引用。以前分配给ptr_var的旧地址仍在内存中。我仍然可以使用旧地址从struct ptr_var打印成员的值。下面的GDB会话显示我正在使用其地址

打印struct ptr_var的字符串成员
(gdb) x /s *0x7e11c0
0x7e0810:   "Sample String"

我无法判断变量ptr_var何时被分配了无效地址0x0。我是GDB的新手,也是普通的C程序员。非常感谢您对此事的帮助。谢谢。

3 个答案:

答案 0 :(得分:2)

您要做的是设置观察点,每次修改结构的成员时,GDB都会停止执行。

使用以下示例代码

typedef struct {
    int val;
 } Foo;

int main(void) {
    Foo foo;
    foo.val = 5;
    foo.val = 10;
}

在创建结构时删除断点并执行watch -l foo.val然后每次更改该成员时,您将获得休息。以下是我的GDB会话,我的输入

(gdb) break test.c:8
Breakpoint 3 at 0x4006f9: file test.c, line 8.
(gdb) run
Starting program: /usr/home/sean/a.out

Breakpoint 3, main () at test.c:9
9               foo.val = 5;
(gdb) watch -l foo.val
Hardware watchpoint 4: -location foo.val
(gdb) cont
Continuing.
Hardware watchpoint 4: -location foo.val

Old value = 0
New value = 5
main () at test.c:10
(gdb) cont
Continuing.
Hardware watchpoint 4: -location foo.val

Old value = 5
New value = 10
main () at test.c:11
(gdb) cont

答案 1 :(得分:1)

如果您可以重新运行,那么在ptr_var正确的位置休息,您可以在ptr_var上设置一个观察点,如下所示:(gdb) watch ptr_var。现在当你每次ptr_var被修改时你继续gdb应该停止。

这是一个例子。这确实包含未定义的行为,因为我试图重现一个错误,但希望它应该足以告诉你我所建议的内容:

#include <stdio.h>
#include <stdint.h>

int target1;
int target2;

void
bad_func (int **bar)
{
  /* Set contents of bar.  */
  uintptr_t ptr = (uintptr_t) bar;
  printf ("Should clear %p\n", (void *) ptr);
  ptr += sizeof (int *);
  printf ("Will clear %p\n", (void *) ptr);

  /* Bad! We just corrupted foo (maybe).  */
  *((int **) ptr) = NULL;
}

int
main ()
{
  int *foo = &target1;
  int *bar = &target2;
  printf ("&foo = %p\n", (void *) &foo);
  printf ("&boo = %p\n", (void *) &bar);
  bad_func (&bar);    
  return *foo;
}

这是一个gdb会话:

(gdb) break bad_func 
Breakpoint 1 at 0x400542: file watch.c, line 11.
(gdb) r

&foo = 0x7fffffffdb88
&boo = 0x7fffffffdb80

Breakpoint 1, bad_func (bar=0x7fffffffdb80) at watch.c:11
11    uintptr_t ptr = (uintptr_t) bar;
(gdb) up
#1  0x00000000004005d9 in main () at watch.c:27
27    bad_func (&bar);
(gdb) watch foo
Hardware watchpoint 2: foo
(gdb) c
Continuing.
Should clear 0x7fffffffdb80
Will clear 0x7fffffffdb88
Hardware watchpoint 2: foo

Old value = (int *) 0x60103c <target1>
New value = (int *) 0x0
bad_func (bar=0x7fffffffdb80) at watch.c:18
18  }
(gdb) 

由于某些原因,观察点似乎在更改后触发了行,即使我使用-O0编译它,这有点遗憾。尽管如此,它通常足够接近以帮助确定问题。

答案 2 :(得分:0)

对于这类问题,我经常使用旧的电围栏库,它可以用来查找“超出malloc()内存分配边界的软件”中的错误。您将在此页面找到所有说明和基本用法: http://elinux.org/Electric_Fence

(在上面链接的页面的最后,您将找到下载链接)