我有以下 C 代码(我将其缩短了一些其他调用和检查):
#include <stdint.h>
#include <memory.h>
extern char buffer[];
extern void getstr1(char *buff, int buflen);
extern void getstr2(char **s);
extern void dosomething(char *s);
void myfn()
{
char *s, *s1;
int len;
getstr1(buffer, 128);
getstr2(&s);
len = *s + *buffer;
memcpy(buffer + *buffer + 1, s + 1, (*s) * sizeof(char));
*buffer = len;
dosomething(buffer);
}
带有/O2 优化选项的 MSVC 产生以下输出:
_s$ = -4 ; size = 4
void myfn(void) PROC ; myfn, COMDAT
push ecx
push 128 ; 00000080H
push OFFSET char * buffer ; buffer
call void getstr1(char *,int) ; getstr1
lea eax, DWORD PTR _s$[esp+12]
push eax
call void getstr2(char * *) ; getstr2
mov eax, DWORD PTR _s$[esp+16]
push OFFSET char * buffer ; buffer
mov al, BYTE PTR [eax]
add BYTE PTR char * buffer, al
call void dosomething(char *) ; dosomething
add esp, 20 ; 00000014H
ret 0
void myfn(void) ENDP ; myfn
您可以查看 on Godbolt
为什么编译器忽略了 memcpy 调用?有趣的是,将外部变量声明为“extern char buffer[N];”其中 N >= 2 或作为“extern char *buffer;”使编译器使用 memcpy。也用 memmove 替换 memcpy 做同样的事情。当源区域和目标区域重叠时,我知道可能的 UB,但这里编译器不知道这一点。
最佳答案
我认为这是 MSVC 中的一个错误,因为您所做的事情是合法的。
请注意,已经提交了一个类似的错误,标题为:Release build with speed optimize leaves an array uninitialized .
在错误报告中给出的重现问题的代码也使用了一个extern type array[];
根据团队的说法,此问题已在即将发布的版本中修复(未提及)。
关于c++ - 为什么 MSVC 会优化掉这个 memcpy 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55398743/