我有这个密码

memcpy

作为标准C库实现的一部分,它从

src

dest

一次一个字节:

void *memcpy(void *restrict dest, const void *restrict src, size_t len)

{

char *dp = (char *restrict)dest;

const char *sp = (const char *restrict)src;

while( len-- )

{

*dp++ = *sp++;

}

return dest;

}

gcc -O2

,生成的代码是合理的:

memcpy:

.LFB0:

movq %rdi, %rax

testq %rdx, %rdx

je .L2

xorl %ecx, %ecx

.L3:

movzbl (%rsi,%rcx), %r8d

movb %r8b, (%rax,%rcx)

addq $1, %rcx

cmpq %rdx, %rcx

jne .L3

.L2:

ret

.LFE0:

但是,在

gcc -O3

,gcc优化这个简单的逐字节复制到

曼皮西

呼叫:

memcpy:

.LFB0:

testq %rdx, %rdx

je .L7

subq $8, %rsp

call memcpy

addq $8, %rsp

ret

.L7:

movq %rdi, %rax

ret

.LFE0:

由于明显的原因,这是次优的,并且会导致一个segfault。

以下是复制segfault的示例(编译时使用

gcc -O3 -fno-builtin-memcpy test.c memcpy.c

)

test.c

:

#include

#include

int main(void)

{

int c, a[] = {1, 2, 3, 4}, b[4];

memcpy(b, a, sizeof(b));

for( c = 0; c < sizeof(b)/sizeof(b[0]); c++ )

printf("%d\n", b[c]);

return 0;

}

我试过传球

-fno-builtin-memcpy

-fno-loop-optimizations

同样的事情也发生了。

我使用的是GCC 8.3.0版:

Using built-in specs.

COLLECT_GCC=gcc

COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-cros-linux-gnu/8.3.0/lto-wrapper

Target: x86_64-cros-linux-gnu

Configured with: ../configure --prefix=/usr/local --libdir=/usr/local/lib64 --build=x86_64-cros-linux-gnu --host=x86_64-cros-linux-gnu --target=x86_64-cros-linux-gnu --enable-checking=release --disable-multilib --enable-threads=posix --disable-bootstrap --disable-werror --disable-libmpx --enable-static --enable-shared --program-suffix=-8.3.0 --with-arch-64=x86-64

Thread model: posix

gcc version 8.3.0 (GCC)

如何禁用导致副本转换为

曼皮西

调用(最好在编译时使用

-O3

?

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐