[英]Why does MSVC optimize away this memcpy call?
I have the following C code (I shortened it removing some other calls and checks): 我有以下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);
}
MSVC with the /O2 optimization option produces the following output: 带有/ 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
You can check this on Godbolt 你可以在Godbolt上查看
Why did the compiler omit the memcpy call? 为什么编译器会省略memcpy调用? It's interesting that declaring the external variable as "extern char buffer[N];"
有趣的是,将外部变量声明为“extern char buffer [N];” where N >= 2 or as "extern char *buffer;"
其中N> = 2或“extern char * buffer;” makes the compiler use memcpy.
使编译器使用memcpy。 Also replacing memcpy with memmove does the same thing.
用memmove替换memcpy也可以做同样的事情。 I know about possible UB when the source and destination regions overlap but here the compiler doesn't have knowledge of this.
当源和目标区域重叠时,我知道可能的UB,但这里编译器不知道这一点。
I think this is a bug in MSVC as what you are doing is legal. 我认为这是MSVC中的一个错误,因为你所做的是合法的。
Note that there has been a similar bug filed already titled: Release build with speed optimize leaves an array uninitialized . 请注意,已经出现了一个类似的错误标题: 使用速度优化的版本构建使数组未初始化 。
The code given to reproduce the problem in the bug report also uses an extern type array[];
在错误报告中重现问题的代码也使用了
extern type array[];
As per the team, this issue is fixed in an upcoming release (which is not mentioned). 根据团队的说法,此问题已在即将发布的版本中修复(未提及)。
What you do is perfectly legal, this is definitely a bug in MSVC. 你所做的是完全合法的,这绝对是MSVC中的一个错误。
Here is a stripped down version to file a bug report: 这是一个用于提交错误报告的精简版本:
#include <string.h>
extern unsigned char buffer[], *s;
void myfn() {
memcpy(buffer + *buffer + 1, s + 1, *s);
*buffer = 1;
}
Compiles to: 编译为:
void myfn(void) PROC ; myfn, COMDAT
mov BYTE PTR unsigned char * buffer, 1
ret 0
void myfn(void) ENDP ; myfn
Removing the statement *buffer = 1;
删除语句
*buffer = 1;
prevents the code generation bug. 防止代码生成错误。
Check it on Godbolt's Compiler Explorer . 在Godbolt的Compiler Explorer上查看它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.