鉴于堆栈,寄存器的状态,可我们predict的printf的的不确定行为的结果 [英] Given the state of the stack and registers, can we predict the outcome of printf's undefined behavior

查看:181
本文介绍了鉴于堆栈,寄存器的状态,可我们predict的printf的的不确定行为的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是一些简单的C code一类测验:

Here is some simple C code for a class quiz:

#include <stdio.h>

int main() {
  float a = 2.3;
  printf("%d\n", a);
  return 0;
}

编译和运行上:

苹果LLVM版本6.1.0(铛-602.0.53 )(基于LLVM 3.6.0svn)结果
目标: x86_64的 - 苹果-darwin14.5.0

Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0

这code的输出是未定义。我用调试器检查内存附近 A (试图predict输出 X 在gdb的命令)。例如,当地址 A 0x7fff5fbffb98 ,然后靠近&放的背景下,一如下:

The output of this code is undefined. I am trying to predict the output by inspecting the memory near a with the debugger (X command in gdb). For example, when the address of a is 0x7fff5fbffb98, then the context near &a is as follows:

0x7fff5fbffb98: 1075000115
0x7fff5fbffb9c: 0
0x7fff5fbffba0: 1606417336
0x7fff5fbffba4: 32767
0x7fff5fbffba8: -1754266167
0x7fff5fbffbac: 32767
0x7fff5fbffbb0: -1754266167
0x7fff5fbffbb4: 32767

然后的输出的printf 1606417352 。我知道使用了不正确说明当输出是不确定的。出于好奇,我预计这个不确定的行为的输出可能与从运行堆栈或寄存器一些内存,但我还没有想出如何将它相关。

Then the output of printf is 1606417352. I know the output when using an incorrect specifier is undefined. Out of curiosity, I expected the output of this undefined behavior to be related to some memory from the running stack or registers, but I have not figured out how to correlate it.

所以它的地址或寄存器用来设置,它的输出的printf ?换句话说,考虑到运行堆栈的状态,并从所有寄存器中的所有值,我们可以predict(如果有的话如何)这个不确定的行为输出?

So which address or register is used to set the output of this printf? In other words, given the state of the running stack, and all values from all registers, can we predict (and if so how) the output of this undefined behavior?

推荐答案

在AMD64与 SysV的调用约定(几乎每个系统,但Windows使用),最初的几个参数的函数在寄存器中传递的 的这就是为什么你没有看到他们在堆栈上:他们AREN 'T在栈中传递。

On AMD64 with the SysV calling convention (used by nearly every system but Windows), the first few arguments to a function are passed in registers. That's why you don't see them on the stack: They aren't passed on the stack.

具体而言,前几个整数或指针参数在 RDI RSI RDX ,而前几个浮点参数在 XMM0 将xmm1 和 XMM2 。由于 A XMM0 被通过,但的printf 试图读取从 RSI 一个数字,你不会看到你提供的号码,什么之间的相关性被打印出来。

Specifically, the first few integer or pointer arguments are passed in rdi, rsi, rdx, whereas the first few floating point arguments are passed in xmm0, xmm1, and xmm2. Since a is passed in xmm0 but printf attempts to read a number from rsi, you won't see any correlation between the number you supplied and what is printed out.

有关未来的读者:请注意,什么OP尝试做的是未定义行为。 ISO 9899:2011规定了一个 INT 应当通过了%d个,但OP正试图与使用双击(后默认参数促销)。为此,OP应该使用%F 来代替。使用错误的格式说明是不确定的行为。请不要假设观察OP使您的系统保持或任何地方,不写这样的code的。

For future readers: Please note that what OP attempts to do is undefined behavior. ISO 9899:2011 specifies that an int should be passed for %d, but OP is trying to use it with a double (after default argument promotions). For that, OP should use %f instead. Using the wrong formatting specifier is undefined behaviour. Please do not assume that the observations OP make hold on your system or anywhere and don't write this kind of code.

这篇关于鉴于堆栈,寄存器的状态,可我们predict的printf的的不确定行为的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆