[英]Compiler optimization creating a syscall?
我正在以两种模式编译一个相当复杂的应用程序:调试和发布。 如我所见,主要区别是-O0与-O3(如果需要,我可以提供makefile的相关部分)。 我试图尽可能避免生成syscall,因为我正在syscall仿真模式下模拟此应用程序(在其下不运行任何操作系统)。 我目前遇到的问题是,在Release模式下,编译器会生成一个额外的套接字syscall,我不希望发生(并且在Debug模式下不会发生)。
我认为可能会创建套接字的原因是我正在使用pthreads,而我的两个线程正在通过volatile char *通信。 所以我猜测也许当我设置-O3标志时,编译器正在尝试以一种奇特的方式实现它? 但是我不确定这是否是一个合理的假设。
编辑:顺便说一句,代码在C和C ++中
编辑:代码静态链接到以下共享库:
libstdc++.a
libm.a
libglib-2.0.a
-static-libgcc
*special pthreads library*
此外,我发现在二进制文件中发生了对套接字的调用:
8c716: db28 blt.n 8c76a <openlog_internal+0xf2>
8c718: f8d9 1008 ldr.w r1, [r9, #8]
8c71c: 4620 mov r0, r4
8c71e: 2200 movs r2, #0
8c720: f441 2100 orr.w r1, r1, #524288 ; 0x80000
8c724: f001 e97c blx 8da20 <__socket>
8c728: 4b20 ldr r3, [pc, #128] ; (8c7ac <openlog_internal+0x134>)
8c72a: 681b ldr r3, [r3, #0]
8c72c: f8c9 0004 str.w r0, [r9, #4]
8c730: b943 cbnz r3, 8c744 <openlog_internal+0xcc>
8c732: 1c43 adds r3, r0, #1
编辑:我发现了为什么会这样(请参阅下面的答案)。 如果有人对编译器为何如此行事有一个解释,请分享!!!
尽管可以想象到这样的优化,但我还没有听说过,我对此表示怀疑,因为任何系统调用通常都非常昂贵。
如果您使用的是* nix系统,则可以通过查找带有nm
未定义符号来进行验证
nm -u file1.o file2.o | grep socket
应该将缺少的socket
符号显示为
U socket
如果在某处有套接字调用。
正如我所提到的,我怀疑是否存在插入任何系统调用的优化,并且我期望上面的命令行没有输出。
更新:
在我的系统(Ubuntu 12.04,gcc 4.6)上,我在man gcc
发现了以下注意事项
-O2进一步优化。 ...
注意:在Ubuntu 8.10和更高版本中,默认情况下设置-D_FORTIFY_SOURCE = 2,并在-O设置为2或更高时被激活。 这样就可以对几个libc函数进行附加的编译时和运行时检查。 要禁用,请指定-U_FORTIFY_SOURCE或-D_FORTIFY_SOURCE = 0。
因此,也许通过这种或类似的机制,当优化设置为-O2
或-O3
时,会包含一些代码。
经过一整天的调试,事实证明,当要从中复制的字符串是volatile char *时,arm-cross-gcc在-O0和-O1,-O2,-O3下编译strcpy()的方式有所不同。 -O0使用标准用户模式汇编进行编译,而-O1,-O2,-O3使用额外的系统调用(例如套接字,连接和发送)进行编译。
因此,毕竟我最初的直觉是合理的:
“我认为可能会创建套接字的原因是我正在使用pthreads,而我的两个线程正在通过volatile char *通信。因此,我猜测也许编译器在设置时试图以一种奇特的方式实现它。 -O3标志?但是我不确定这是否合理。”
编辑:这是支持此主张的一些观察:
我将代码编译为4个版本
1. without strcpy() -O0 => obj.o0
2. with strcpy() -O0 => obj_strcpy.o0
3. without strcpy() -O3 => obj.o3
4. with strcpy() -O3 => obj_strcpy.o3
我在所有上述情况上都运行了nm -u。
这是差异:
$> diff obj.o0 obj_strcpy.o0
$> diff obj.o3 obj_strcpy.o3
> U __strcpy_chk
$>
这意味着,当您将strcpy()添加到代码中并使用-O0进行编译时,不会添加任何外部符号,而当您将strcpy()添加到您的代码中并使用-O3进行编译时, U __strcpy_chk
符号添加到目标文件中。 我将研究ARM上U __strcpy_chk
的实现,以确定系统调用来自何处。 截至目前,似乎U __strcpy_chk
正在执行缓冲区溢出检查-这是参考:
编辑:到目前为止,有两种解决方案:一种由Olaf Dietsche提出,除了-O3之外还使用另一种编译器标志。 另一种选择是完全避免使用strcpy()并使用如下所示的内容:
for(int i=0;i<64;i++)
{
cmd[i] = msg[i];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.