微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

内存在variables赋值之前不包含垃圾

我有一个简单的C程序:

#include <stdio.h> int main() { int i; for(i = 0; i < 10; i++) printf("Hellon"); return 0; }

我使用gcc编译它:

gcc -g test.c

然后我运行debugging器:

gdb -q ./a.out

我在main中设置了一个断点并运行:

汇编代码在Windows 8 x64上

有人可以解释__declspec(裸体)吗?

如何将反汇编的C代码分解为函数

提示用户inputassemblyci20 seg故障

从x86 asm在Linux中访问命令行参数的问题

(gdb) break main (gdb) run

然后让它运行,直到遇到断点,并试图在rip当前指向的地址上显示汇编指令:

(gdb) x/i $rip => 0x400538 <main+8>: mov DWORD PTR [rbp-0x4],0x0

它看起来像下一个指令将初始化我的本地variables我的值为0.由于它还没有执行的指令,我希望有一个垃圾值在那里。

(gdb) x/4xb $rbp-4 0x7fffffffe0ec: 0x00 0x00 0x00 0x00

它看起来不像垃圾值,看起来所有的东西都已经被清零了。 在执行main中的任何代码之前,断点应该暂停程序。

在这里错过了什么? 在局部variablesi初始化之前,该内存位置是否应该包含随机垃圾值?

为什么gcc生成详细的汇编代码

想学习大会,困惑从哪里开始

Linux汇编debugging器

这个方法好吗?

帮助%es注册x86到x86_64汇编代码端口

它看起来不像垃圾值,看起来所有的东西都已经被清零了。

修改了你的例子,以表明这只是一个巧合。

#include <stdio.h> int main() { int i1; int i2; int i3; int i4; int i5; int i6; int i; for(i = 0; i < 10; i++) printf("Hellon"); return 0; }

(gdb) start Temporary breakpoint 1 at 0x4005ac: file main.cpp,line 13. Starting program: /home/a.out Temporary breakpoint 1,main () at main.cpp:13 13 for(i = 0; i < 10; i++) (gdb) info locals i1 = 0 i3 = 0 i5 = 32767 i = 0 i2 = 4195520 i4 = -7856 i6 = 0

你看,不同的价值是可能的。

至于你的例子,这个地址的值在到达main()之前至少改变两次。 只要设置这个地址,你会发现它在main()之前调用函数中被改变了:

(gdb) watch *(int*)0x7fffffffe06c Hardware watchpoint 1: *(int*)0x7fffffffe06c (gdb) r Starting program: /home/a.out Hardware watchpoint 1: *(int*)0x7fffffffe06c Old value = 0 New value = 58 0x0000003a1d890880 in handle_intel () from /lib64/libc.so.6 Hardware watchpoint 1: *(int*)0x7fffffffe06c Old value = 58 New value = 0 0x0000003a1d0146fd in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2 Hardware watchpoint 1: *(int*)0x7fffffffe06c Old value = 0 New value = 1 0x00000000004005c3 in main () at main.cpp:7 7 for(i = 0; i < 10; i++) #0 0x00000000004005c3 in main () at main.cpp:7

垃圾值可能是任何东西,包括值0.该局部变量的内容是未定义的,直到它被赋值的地步。 在这种情况发生之前,你不能期望内容是某种类型的。

然而,在调试构建过程中,所有局部变量都进行了零调整是非常常见的。 如果这是gdb的情况,我不知道。 你可以在初始化之前尝试打印变量的内容,然后在没有调试器的情况下建立一个版本,看看这个行为是否相同。

更可能的是,编译器做出了比实际行i = 0更早的初始化变量的决定。 如果编译器可以确定这样做不会影响程序结果,编译器可以自由地改变程序的执行顺序。 由于性能的原因,编译器可能已经将零点移出到程序的较早点。

你误解了什么是“垃圾”(甚至不是一个正式的术语)。 C中未初始化的对象具有不确定的值 。 这并不意味着这个值是随机的,更不用说它具有任何熵的价值了(实际上,在Heartbleed发生之前,这个误解实际上已经发生了OpenSSL / Debian的巨大失败,并且每个人都意识到OpenSSL是多么的混乱)。 这意味着你不能使用这个值 。 如果你这样做,你没有一个有效的C程序,而是一个毫无意义的程序,试图推断它的作用没有意义(除非你是一个试图利用程序中的漏洞的攻击者)。

它看起来不像垃圾

在这种情况下,“零”只是一个垃圾值”(或更正确的值)的特殊情况,在任何情况下都不能依赖,这是一个稍微修改的例子,它在我的编译器上产生了不同的值( gcc 4.4.7 ):

#include <stdio.h> int main(void) { int i,j,k; for(i = 0; i < 10; i++) printf("Hellon"); return 0; }

和gdb会话:

Breakpoint 1,main () at check.c:6 6 for(i = 0; i < 10; i++) (gdb) x/i $pc => 0x4004cc <main+8>: mov DWORD PTR [rbp-0xc],0x0 (gdb) x/4xb $rbp-0xc 0x7fffffffe124: 0xff 0x7f 0x00 0x00

好的比喻可能是随机数字发生器,返回零。 零和112或377是相同的随机值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐