为什么MSVC优化了此memcpy调用?

ole*_*que 15 c c++

我有以下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);
}
Run Code Online (Sandbox Code Playgroud)

带有/ 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
Run Code Online (Sandbox Code Playgroud)

你可以在Godbolt上检查一下

为什么编译器忽略了memcpy调用?将外部变量声明为“ extern char buffer [N];”很有趣。其中N> = 2或作为“ extern char * buffer;” 使编译器使用memcpy。同样用memmove代替memcpy也可以做到这一点。当源区域和目标区域重叠时,我知道可能的UB,但是在此编译器不知道这一点。

P.W*_*P.W 11

我认为这是MSVC中的错误,因为您所做的是合法的。

请注意,已经有一个类似的Bug题为:使用speedoptim进行发布构建会使数组未初始化

错误报告中用于重现该问题的代码也使用了 extern type array[];

根据团队,此问题已在即将发布的版本中解决(未提及)。

  • 似乎不太可能在没有任何人注意的情况下拥有12年的错误? (2认同)