我相信在构建大型项目时会遇到编译器错误。仅当使用-O1(而不是-O0或-O2)编译代码时,才观察到有问题的代码生成。
问题在于函数调用,该函数调用是find_if的包装。此函数将一个空向量作为输入,该向量应使find_if立即返回。
代码看起来像这样:
void LookUpEvalResultFun(some arguments) {
empty vector declaration
some simple code handling the arguments
call the function that is wrapper to find_if
}
如果代码的行为不符合预期,则汇编器如下所示:
0x00eab0dc <+0>: strd r4, [sp, #-36]! ; 0xffffffdc
0x00eab0e0 <+4>: strd r6, [sp, #8]
0x00eab0e4 <+8>: strd r8, [sp, #16]
0x00eab0e8 <+12>: strd r10, [sp, #24]
0x00eab0ec <+16>: str lr, [sp, #32]
0x00eab0f0 <+20>: add r11, sp, #32
0x00eab0f4 <+24>: sub sp, sp, #132 ; 0x84
0x00eab0f8 <+28>: ldr r3, [r0]
0x00eab0fc <+32>: ldr r3, [r3, #24]
0x00eab100 <+36>: blx r3
0x00eab104 <+40>: movw r4, #21700 ; 0x54c4
0x00eab108 <+44>: movt r4, #373 ; 0x175
0x00eab10c <+48>: mov r3, #0
0x00eab110 <+52>: strb r3, [sp]
0x00eab114 <+56>: ldr r2, [r4, #52] ; 0x34
0x00eab118 <+60>: ldr r0, [r4, #48] ; 0x30
0x00eab11c <+64>: bl 0xd9c4a0 <mangled name for find_if>
mangled name for find_if:
0x00d9c4a0 <+0>: strd r4, [sp, #-32]! ; 0xffffffe0
0x00d9c4a4 <+4>: strd r6, [sp, #8]
0x00d9c4a8 <+8>: strd r8, [sp, #16]
0x00d9c4ac <+12>: str r11, [sp, #24]
0x00d9c4b0 <+16>: str lr, [sp, #28]
0x00d9c4b4 <+20>: add r11, sp, #28
0x00d9c4b8 <+24>: mov r9, r1
0x00d9c4bc <+28>: mov r7, r0
0x00d9c4c0 <+32>: rsb r8, r0, r1
0x00d9c4c4 <+36>: asr r8, r8, #6
0x00d9c4c8 <+40>: movw r3, #43691 ; 0xaaab
0x00d9c4cc <+44>: movt r3, #43690 ; 0xaaaa
0x00d9c4d0 <+48>: mul r8, r3, r8
0x00d9c4d4 <+52>: asr r8, r8, #2
0x00d9c4d8 <+56>: cmp r8, #0
0x00d9c4dc <+60>: ble 0xd9c558 <_ZSt9__find_ifIN9__gnu_cxx17__normal_iterator...>
以下说明:
0x00eab114 <+56>: ldr r2, [r4, #52] ; 0x34
0x00eab118 <+60>: ldr r0, [r4, #48] ; 0x30
vs。
0x00d9c4b8 <+24>: mov r9, r1
0x00d9c4bc <+28>: mov r7, r0
表明在包装函数中R2加载了vector.end(),而find_if希望在R1中找到vector.end()。
以下是更有趣的事情,无论有关优化级别的代码如何编译(当使用-c分别编译每个文件时)。
1244: e3a00000 mov r0, #0
template<typename _Iterator, typename _Predicate>
inline _Iterator
__find_if(_Iterator __first, _Iterator __last, _Predicate __pred)
{
return __find_if(__first, __last, __pred, std::__iterator_category(__first));
1248: e3a03000 mov r3, #0
124c: e5cd3000 strb r3, [sp]
1250: e1a02000 mov r2, r0
1254: ebfffffe bl 0 <mangled name>
1254: R_ARM_CALL _ZSt9__find_ifIN9__gnu_cxx17__normal_iterator
00000000 <mangled name>:
0: e16d42f0 strd r4, [sp, #-32]! ; 0xffffffe0
4: e1cd60f8 strd r6, [sp, #8]
8: e1cd81f0 strd r8, [sp, #16]
c: e58db018 str fp, [sp, #24]
10: e58de01c str lr, [sp, #28]
14: e28db01c add fp, sp, #28
18: e1a09002 mov r9, r2
1c: e1a07000 mov r7, r0
20: e0608002 rsb r8, r0, r2
24: e1a08348 asr r8, r8, #6
28: e30a3aab movw r3, #43691 ; 0xaaab
2c: e34a3aaa movt r3, #43690 ; 0xaaaa
这表明正确使用了R2!
我的理论是这样的:
即使addr2line也会显示以下内容:
0x00001254: _ZSt9__find_ifIN9__gnu_cxx17__normal_iteratorIPKN2ue7VariantINS2_12_...
(inlined by) _ZSt7find_ifIN9__gnu_cxx17__normal_iteratorIPKN2ue7VariantINS2_12_...
(inlined by) find_if wrapper
(inlined by) LookUpEvalResultFun at ...
表明objdump没有说谎;某种程度上支持了第一种理论。
您有什么想法吗?
谢谢。