使用-fno-builtin的GCC似乎不起作用

时间:2014-08-12 19:30:55

标签: c++ gcc memcpy

我想将GCC内置函数memcpy与libc中的函数进行比较。但是,-fno-builtin-fno-builtin-memcpy的所有迭代似乎都会被忽略。

//g++ -O3 foo.cpp -S or
//g++ -O3 -fno-builtin foo.cpp -S
#include <string.h>
int main() {
    volatile int n = 1000;
    //int n = 1000;
    float *x = new float[1000];
    float *y = new float[1000];
    memcpy(y,x,sizeof(float)*n);
    //__builtin_memcpy(y,x,sizeof(float)*n);    
}

我发现如果上面的源代码中的n不是易变的,那么它会内置代码。但是,当n变为易失性时,它会调用函数__memcpy_chk,这是memcpy with buffer overflow checking的版本。如果n不稳定,我会拨打__builtin_memcpy,然后调用memcpy

所以到目前为止我的结论是,只有在编译时知道n并且-fno-builtin无效时才会生成内置代码。我正在使用GCC 4.8.2。

-fno-builtin已过时吗?有没有办法在C库中调用memcpy即使在编译时知道n

3 个答案:

答案 0 :(得分:4)

-fno-builtin-fno-builtin-memcpy都会产生您对gcc 4.9.1的预期效果。这可能只是gcc 4.8.2中的一个错误;这种特殊的选项组合并未得到广泛应用。 -ffreestanding是一个相关的开关,可能具有您想要的效果4.8.2。

请注意,编译器可以将程序优化到

int main() { return 0; }

在没有-fno-builtin(-memcpy)-ffreestanding的情况下调用,即使nvolatile,因为它(原则上)可以证明整个程序无法观察到副作用,或其行为未定义。 (当n volatile时,不能有UB;如果n在读取时超出范围[0, 1000],则会发生UB,{ {1}}告诉编译器它不能假定volatile具有程序写入它的值。)

答案 1 :(得分:1)

注意:因为您正在编译C ++代码,所以我不能100%确定是否适用。

C标准要求所有库函数(除非另有明确说明)具有地址,并且可以是&地址运算符的操作数。这是因为它允许将一些/大多数函数实现为功能宏,但在某些情况下仍然应该像实际的变量/函数一样。为了避免它的宏版本,你只需要memcpy令牌和(令牌之间的某些东西(正如@Zach指出的那样,空格不足):

(memcpy)(y, x, ...)

这会强制使用实际的函数,应该避免任何类型的内置宏定义。


同样可能(阅读:可能)-O3优化扫描某些函数调用(例如memcpy)并用内置调用替换它们,而不管{{1} }。

答案 2 :(得分:1)

您的问题很可能是glibc,而不是gcc。您没有指定,但可能使用的是Ubuntu,默认情况下定义了-D_FORTIFY_SOURCE=2。这会提示glibc标头提供memcpy的内联定义,该定义转发到__memcpy_chk