繁体   English   中英

编译器优化创建了系统调用?

[英]Compiler optimization creating a syscall?

我正在以两种模式编译一个相当复杂的应用程序:调试和发布。 如我所见,主要区别是-O0与-O3(如果需要,我可以提供makefile的相关部分)。 我试图尽可能避免生成syscall,因为我正在syscall仿真模式下模拟此应用程序(在其下不运行任何操作系统)。 我目前遇到的问题是,在Release模式下,编译器会生成一个额外的套接字syscall,我不希望发生(并且在Debug模式下不会发生)。

我认为可能会创建套接字的原因是我正在使用pthreads,而我的两个线程正在通过volatile char *通信。 所以我猜测也许当我设置-O3标志时,编译器正在尝试以一种奇特的方式实现它? 但是我不确定这是否是一个合理的假设。

  1. 是否可能由于-O3标志而正在生成套接字syscall? (没有太大意义)
  2. 如果是这样,我如何向编译器提示以避免生成此syscall?

编辑:顺便说一句,代码在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正在执行缓冲区溢出检查-这是参考:

http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/libc---strcpy-chk-1.html

编辑:到目前为止,有两种解决方案:一种由Olaf Dietsche提出,除了-O3之外还使用另一种编译器标志。 另一种选择是完全避免使用strcpy()并使用如下所示的内容:

for(int i=0;i<64;i++)
{
  cmd[i] = msg[i];
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM