我在一个更大的程序中有一个内部函数,它以某种方式将浮点值更改为" nan"当我预计它为零。我已将函数修剪为最简单的形式,没有参数:
static void func(void)
{
int a = 1;
float x = 0.0f;
float v = 0.0f;
printf("x(%f), ", x);
x += (float)a * v;
printf("x(%f), ", x);
printf("(int)x: %d, ", (int)x);
}
这给出了输出:
x(0.000000), x(nan), (int)x: -2147483648
如果我删除变量a
并对值(1)进行硬编码,则nan值消失。同样,如果我删除行x += (float)a * v;
,则所有内容都按预期打印(全为零)。
令人沮丧的是,我无法通过创建一个新程序并在main()
中抛弃它来重现这一点。当我尝试这个时,程序运行完美并输出:
x(0.000000), x(0.000000), (int)x: 0
从实际程序中的函数中反汇编:
00000029 <_func>:
29: 55 push %ebp
2a: 89 e5 mov %esp,%ebp
2c: 83 ec 38 sub $0x38,%esp
2f: c7 45 f4 01 00 00 00 movl $0x1,-0xc(%ebp)
36: a1 18 00 00 00 mov 0x18,%eax
3b: 89 45 f0 mov %eax,-0x10(%ebp)
3e: a1 18 00 00 00 mov 0x18,%eax
43: 89 45 ec mov %eax,-0x14(%ebp)
46: d9 45 f0 flds -0x10(%ebp)
49: dd 5c 24 04 fstpl 0x4(%esp)
4d: c7 04 24 00 00 00 00 movl $0x0,(%esp)
54: e8 a7 ff ff ff call 0 <_printf>
59: d9 45 f0 flds -0x10(%ebp)
5c: db 45 f4 fildl -0xc(%ebp)
5f: d9 5d e4 fstps -0x1c(%ebp)
62: d9 45 e4 flds -0x1c(%ebp)
65: d9 45 ec flds -0x14(%ebp)
68: de c9 fmulp %st,%st(1)
6a: de c1 faddp %st,%st(1)
6c: d9 5d f0 fstps -0x10(%ebp)
6f: d9 45 f0 flds -0x10(%ebp)
72: dd 5c 24 04 fstpl 0x4(%esp)
76: c7 04 24 00 00 00 00 movl $0x0,(%esp)
7d: e8 7e ff ff ff call 0 <_printf>
82: d9 45 f0 flds -0x10(%ebp)
85: d9 7d e2 fnstcw -0x1e(%ebp)
88: 0f b7 45 e2 movzwl -0x1e(%ebp),%eax
8c: b4 0c mov $0xc,%ah
8e: 66 89 45 e0 mov %ax,-0x20(%ebp)
92: d9 6d e0 fldcw -0x20(%ebp)
95: db 5d dc fistpl -0x24(%ebp)
98: d9 6d e2 fldcw -0x1e(%ebp)
9b: 8b 45 dc mov -0x24(%ebp),%eax
9e: 89 44 24 04 mov %eax,0x4(%esp)
a2: c7 04 24 08 00 00 00 movl $0x8,(%esp)
a9: e8 52 ff ff ff call 0 <_printf>
ae: c9 leave
af: c3 ret
从独立功能(作为main()
)进行反汇编:
00000000 <_main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 30 sub $0x30,%esp
9: e8 00 00 00 00 call e <_main+0xe>
e: c7 44 24 2c 01 00 00 movl $0x1,0x2c(%esp)
15: 00
16: a1 18 00 00 00 mov 0x18,%eax
1b: 89 44 24 28 mov %eax,0x28(%esp)
1f: a1 18 00 00 00 mov 0x18,%eax
24: 89 44 24 24 mov %eax,0x24(%esp)
28: d9 44 24 28 flds 0x28(%esp)
2c: dd 5c 24 04 fstpl 0x4(%esp)
30: c7 04 24 00 00 00 00 movl $0x0,(%esp)
37: e8 00 00 00 00 call 3c <_main+0x3c>
3c: db 44 24 2c fildl 0x2c(%esp)
40: d8 4c 24 24 fmuls 0x24(%esp)
44: d9 44 24 28 flds 0x28(%esp)
48: de c1 faddp %st,%st(1)
4a: d9 5c 24 28 fstps 0x28(%esp)
4e: d9 44 24 28 flds 0x28(%esp)
52: dd 5c 24 04 fstpl 0x4(%esp)
56: c7 04 24 00 00 00 00 movl $0x0,(%esp)
5d: e8 00 00 00 00 call 62 <_main+0x62>
62: d9 44 24 28 flds 0x28(%esp)
66: d9 7c 24 1e fnstcw 0x1e(%esp)
6a: 0f b7 44 24 1e movzwl 0x1e(%esp),%eax
6f: b4 0c mov $0xc,%ah
71: 66 89 44 24 1c mov %ax,0x1c(%esp)
76: d9 6c 24 1c fldcw 0x1c(%esp)
7a: db 5c 24 18 fistpl 0x18(%esp)
7e: d9 6c 24 1e fldcw 0x1e(%esp)
82: 8b 44 24 18 mov 0x18(%esp),%eax
86: 89 44 24 04 mov %eax,0x4(%esp)
8a: c7 04 24 08 00 00 00 movl $0x8,(%esp)
91: e8 00 00 00 00 call 96 <_main+0x96>
96: b8 00 00 00 00 mov $0x0,%eax
9b: c9 leave
9c: c3 ret
9d: 90 nop
9e: 90 nop
9f: 90 nop
答案 0 :(得分:0)
此问题通常是未定义行为的结果。在这个特定的例子中,有一个隐式函数声明(一个头文件没有包含在程序的其他地方)导致UB,并导致了这个错误。