Why does MSVC optimize away this memcpy call?Why does printf not flush after the call unless a newline is in the format string?Error while Trying to Hook “TerminateProcess” Function. Target Process crashes. Can anyone help me?PeekMessage() throws an unhandled exception (access violation)Jumping to the next “instruction” using gdbWhy does sizeof(x++) not increment x?Why does changing 0.1f to 0 slow down performance by 10x?CppUTest: how to pass more data to a specific mock call?Why does the C preprocessor interpret the word “linux” as the constant “1”?Why does GCC generate 15-20% faster code if I optimize for size instead of speed?20 bytes are reserved on the stack for no apparent reason when C code is compiled into machine code
Amortized Loans seem to benefit the bank more than the customer
Is the name of an interval between two notes unique and absolute?
Is there a theorem in Real analysis similar to Cauchy's theorem in Complex analysis?
How to make classical firearms effective on space habitats despite the coriolis effect?
Are omoplatas legal in judo?
What is the maximum viable speed for a projectile within earth's atmosphere?
How can I create folders in folders in terminal
How important is weather sealing for a winter trip?
How to give my students a straightedge instead of a ruler
What's the purpose of autocorrelation?
Paradox regarding phase transitions in relativistic systems
What’s a “dissipated” garment supposed to be?
MySQL - How to check for a value in all columns
Why do things cool off?
What the did the controller say during my approach to land (audio clip)?
Can I separate garlic into cloves for storage?
Can we have a C++ function with multiple return types? ( C++11 and above)
Is a global DNS record a security risk for phpMyAdmin?
Plot irregular circle in latex
Microservices and Stored Procedures
Talk about Grandpa's weird talk: Who are these folks?
What does the Free Recovery sign (UK) actually mean?
Tips for remembering the order of parameters for ln?
Do encumbered characters suffer any penalties when exploring and/or traveling?
Why does MSVC optimize away this memcpy call?
Why does printf not flush after the call unless a newline is in the format string?Error while Trying to Hook “TerminateProcess” Function. Target Process crashes. Can anyone help me?PeekMessage() throws an unhandled exception (access violation)Jumping to the next “instruction” using gdbWhy does sizeof(x++) not increment x?Why does changing 0.1f to 0 slow down performance by 10x?CppUTest: how to pass more data to a specific mock call?Why does the C preprocessor interpret the word “linux” as the constant “1”?Why does GCC generate 15-20% faster code if I optimize for size instead of speed?20 bytes are reserved on the stack for no apparent reason when C code is compiled into machine code
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I have the following C code (I shortened it removing some other calls and checks):
#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:
_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
Why did the compiler omit the memcpy call? It's interesting that declaring the external variable as "extern char buffer[N];" where N >= 2 or as "extern char *buffer;" makes the compiler use memcpy. Also replacing memcpy with memmove does the same thing. I know about possible UB when the source and destination regions overlap but here the compiler doesn't have knowledge of this.
c++ c
|
show 19 more comments
I have the following C code (I shortened it removing some other calls and checks):
#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:
_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
Why did the compiler omit the memcpy call? It's interesting that declaring the external variable as "extern char buffer[N];" where N >= 2 or as "extern char *buffer;" makes the compiler use memcpy. Also replacing memcpy with memmove does the same thing. I know about possible UB when the source and destination regions overlap but here the compiler doesn't have knowledge of this.
c++ c
2
Isextern char buffer[];legal?
– NathanOliver
Mar 28 at 13:29
1
@Ctx right, but with either casesizeof bufferdoesn't make much sense anyway.
– Jabberwocky
Mar 28 at 13:33
1
I tried both C and C++: the result is the same. Initially it was C code. More details: the issue can be reproduced with MSVC 2005 and with modern compilers too (some of them you can check on godbolt.org).
– oleque
Mar 28 at 13:41
2
Well, C or C++ matters because C++ has a standard header calledmemorybut C has no such thing, apart from I believe some non-standard Linux header. Maybe there's also some MS trash called memory.h? I can't find it in MSDN. What I'm getting at is that you haven't includedstring.hwhich is required for memcpy. VS, being barely compliant with C90 at best, might then go bananas and assume the prototype isint memcpy(int, int, int);because they probably don't follow C99 either. It's really hard to guess what this so-called "compiler" does and doesn't.
– Lundin
Mar 28 at 13:46
2
extern char buffer[];is legal. Additionally it is nothing likeextern char *buffer;.
– Antti Haapala
Mar 28 at 13:52
|
show 19 more comments
I have the following C code (I shortened it removing some other calls and checks):
#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:
_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
Why did the compiler omit the memcpy call? It's interesting that declaring the external variable as "extern char buffer[N];" where N >= 2 or as "extern char *buffer;" makes the compiler use memcpy. Also replacing memcpy with memmove does the same thing. I know about possible UB when the source and destination regions overlap but here the compiler doesn't have knowledge of this.
c++ c
I have the following C code (I shortened it removing some other calls and checks):
#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:
_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
Why did the compiler omit the memcpy call? It's interesting that declaring the external variable as "extern char buffer[N];" where N >= 2 or as "extern char *buffer;" makes the compiler use memcpy. Also replacing memcpy with memmove does the same thing. I know about possible UB when the source and destination regions overlap but here the compiler doesn't have knowledge of this.
c++ c
c++ c
edited Mar 28 at 20:07
Boann
39k13 gold badges93 silver badges123 bronze badges
39k13 gold badges93 silver badges123 bronze badges
asked Mar 28 at 13:23
olequeoleque
1181 silver badge8 bronze badges
1181 silver badge8 bronze badges
2
Isextern char buffer[];legal?
– NathanOliver
Mar 28 at 13:29
1
@Ctx right, but with either casesizeof bufferdoesn't make much sense anyway.
– Jabberwocky
Mar 28 at 13:33
1
I tried both C and C++: the result is the same. Initially it was C code. More details: the issue can be reproduced with MSVC 2005 and with modern compilers too (some of them you can check on godbolt.org).
– oleque
Mar 28 at 13:41
2
Well, C or C++ matters because C++ has a standard header calledmemorybut C has no such thing, apart from I believe some non-standard Linux header. Maybe there's also some MS trash called memory.h? I can't find it in MSDN. What I'm getting at is that you haven't includedstring.hwhich is required for memcpy. VS, being barely compliant with C90 at best, might then go bananas and assume the prototype isint memcpy(int, int, int);because they probably don't follow C99 either. It's really hard to guess what this so-called "compiler" does and doesn't.
– Lundin
Mar 28 at 13:46
2
extern char buffer[];is legal. Additionally it is nothing likeextern char *buffer;.
– Antti Haapala
Mar 28 at 13:52
|
show 19 more comments
2
Isextern char buffer[];legal?
– NathanOliver
Mar 28 at 13:29
1
@Ctx right, but with either casesizeof bufferdoesn't make much sense anyway.
– Jabberwocky
Mar 28 at 13:33
1
I tried both C and C++: the result is the same. Initially it was C code. More details: the issue can be reproduced with MSVC 2005 and with modern compilers too (some of them you can check on godbolt.org).
– oleque
Mar 28 at 13:41
2
Well, C or C++ matters because C++ has a standard header calledmemorybut C has no such thing, apart from I believe some non-standard Linux header. Maybe there's also some MS trash called memory.h? I can't find it in MSDN. What I'm getting at is that you haven't includedstring.hwhich is required for memcpy. VS, being barely compliant with C90 at best, might then go bananas and assume the prototype isint memcpy(int, int, int);because they probably don't follow C99 either. It's really hard to guess what this so-called "compiler" does and doesn't.
– Lundin
Mar 28 at 13:46
2
extern char buffer[];is legal. Additionally it is nothing likeextern char *buffer;.
– Antti Haapala
Mar 28 at 13:52
2
2
Is
extern char buffer[]; legal?– NathanOliver
Mar 28 at 13:29
Is
extern char buffer[]; legal?– NathanOliver
Mar 28 at 13:29
1
1
@Ctx right, but with either case
sizeof buffer doesn't make much sense anyway.– Jabberwocky
Mar 28 at 13:33
@Ctx right, but with either case
sizeof buffer doesn't make much sense anyway.– Jabberwocky
Mar 28 at 13:33
1
1
I tried both C and C++: the result is the same. Initially it was C code. More details: the issue can be reproduced with MSVC 2005 and with modern compilers too (some of them you can check on godbolt.org).
– oleque
Mar 28 at 13:41
I tried both C and C++: the result is the same. Initially it was C code. More details: the issue can be reproduced with MSVC 2005 and with modern compilers too (some of them you can check on godbolt.org).
– oleque
Mar 28 at 13:41
2
2
Well, C or C++ matters because C++ has a standard header called
memory but C has no such thing, apart from I believe some non-standard Linux header. Maybe there's also some MS trash called memory.h? I can't find it in MSDN. What I'm getting at is that you haven't included string.h which is required for memcpy. VS, being barely compliant with C90 at best, might then go bananas and assume the prototype is int memcpy(int, int, int); because they probably don't follow C99 either. It's really hard to guess what this so-called "compiler" does and doesn't.– Lundin
Mar 28 at 13:46
Well, C or C++ matters because C++ has a standard header called
memory but C has no such thing, apart from I believe some non-standard Linux header. Maybe there's also some MS trash called memory.h? I can't find it in MSDN. What I'm getting at is that you haven't included string.h which is required for memcpy. VS, being barely compliant with C90 at best, might then go bananas and assume the prototype is int memcpy(int, int, int); because they probably don't follow C99 either. It's really hard to guess what this so-called "compiler" does and doesn't.– Lundin
Mar 28 at 13:46
2
2
extern char buffer[]; is legal. Additionally it is nothing like extern char *buffer;.– Antti Haapala
Mar 28 at 13:52
extern char buffer[]; is legal. Additionally it is nothing like extern char *buffer;.– Antti Haapala
Mar 28 at 13:52
|
show 19 more comments
2 Answers
2
active
oldest
votes
I think this is a bug in MSVC as what you are doing is legal.
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[];
As per the team, this issue is fixed in an upcoming release (which is not mentioned).
... "nice"... and the "interrim stopgap fix" is to modify all C source code.
– Antti Haapala
Mar 28 at 14:00
2
Seems unlikely that they had this bug for 12 years without anyone noticing though?
– Lundin
Mar 28 at 14:00
@Lundin Or.. they don't care?
– Eugene Sh.
Mar 28 at 14:01
Yes, it looks like the same bug but they wrote VS2015 produced correct output. On godbolt site you can try both of them and result is the same (memcpy call missing).
– oleque
Mar 28 at 14:12
fixed in an upcoming release Not sure if that means VS2019 or one of the VS2017 releases. I would not expect any older compiler to be fixed.
– drescherjm
Mar 28 at 14:15
|
show 1 more comment
What you do is perfectly legal, this is definitely a bug in 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; prevents the code generation bug.
Check it on Godbolt's Compiler Explorer.
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55398743%2fwhy-does-msvc-optimize-away-this-memcpy-call%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I think this is a bug in MSVC as what you are doing is legal.
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[];
As per the team, this issue is fixed in an upcoming release (which is not mentioned).
... "nice"... and the "interrim stopgap fix" is to modify all C source code.
– Antti Haapala
Mar 28 at 14:00
2
Seems unlikely that they had this bug for 12 years without anyone noticing though?
– Lundin
Mar 28 at 14:00
@Lundin Or.. they don't care?
– Eugene Sh.
Mar 28 at 14:01
Yes, it looks like the same bug but they wrote VS2015 produced correct output. On godbolt site you can try both of them and result is the same (memcpy call missing).
– oleque
Mar 28 at 14:12
fixed in an upcoming release Not sure if that means VS2019 or one of the VS2017 releases. I would not expect any older compiler to be fixed.
– drescherjm
Mar 28 at 14:15
|
show 1 more comment
I think this is a bug in MSVC as what you are doing is legal.
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[];
As per the team, this issue is fixed in an upcoming release (which is not mentioned).
... "nice"... and the "interrim stopgap fix" is to modify all C source code.
– Antti Haapala
Mar 28 at 14:00
2
Seems unlikely that they had this bug for 12 years without anyone noticing though?
– Lundin
Mar 28 at 14:00
@Lundin Or.. they don't care?
– Eugene Sh.
Mar 28 at 14:01
Yes, it looks like the same bug but they wrote VS2015 produced correct output. On godbolt site you can try both of them and result is the same (memcpy call missing).
– oleque
Mar 28 at 14:12
fixed in an upcoming release Not sure if that means VS2019 or one of the VS2017 releases. I would not expect any older compiler to be fixed.
– drescherjm
Mar 28 at 14:15
|
show 1 more comment
I think this is a bug in MSVC as what you are doing is legal.
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[];
As per the team, this issue is fixed in an upcoming release (which is not mentioned).
I think this is a bug in MSVC as what you are doing is legal.
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[];
As per the team, this issue is fixed in an upcoming release (which is not mentioned).
answered Mar 28 at 13:47
P.WP.W
22.2k4 gold badges23 silver badges61 bronze badges
22.2k4 gold badges23 silver badges61 bronze badges
... "nice"... and the "interrim stopgap fix" is to modify all C source code.
– Antti Haapala
Mar 28 at 14:00
2
Seems unlikely that they had this bug for 12 years without anyone noticing though?
– Lundin
Mar 28 at 14:00
@Lundin Or.. they don't care?
– Eugene Sh.
Mar 28 at 14:01
Yes, it looks like the same bug but they wrote VS2015 produced correct output. On godbolt site you can try both of them and result is the same (memcpy call missing).
– oleque
Mar 28 at 14:12
fixed in an upcoming release Not sure if that means VS2019 or one of the VS2017 releases. I would not expect any older compiler to be fixed.
– drescherjm
Mar 28 at 14:15
|
show 1 more comment
... "nice"... and the "interrim stopgap fix" is to modify all C source code.
– Antti Haapala
Mar 28 at 14:00
2
Seems unlikely that they had this bug for 12 years without anyone noticing though?
– Lundin
Mar 28 at 14:00
@Lundin Or.. they don't care?
– Eugene Sh.
Mar 28 at 14:01
Yes, it looks like the same bug but they wrote VS2015 produced correct output. On godbolt site you can try both of them and result is the same (memcpy call missing).
– oleque
Mar 28 at 14:12
fixed in an upcoming release Not sure if that means VS2019 or one of the VS2017 releases. I would not expect any older compiler to be fixed.
– drescherjm
Mar 28 at 14:15
... "nice"... and the "interrim stopgap fix" is to modify all C source code.
– Antti Haapala
Mar 28 at 14:00
... "nice"... and the "interrim stopgap fix" is to modify all C source code.
– Antti Haapala
Mar 28 at 14:00
2
2
Seems unlikely that they had this bug for 12 years without anyone noticing though?
– Lundin
Mar 28 at 14:00
Seems unlikely that they had this bug for 12 years without anyone noticing though?
– Lundin
Mar 28 at 14:00
@Lundin Or.. they don't care?
– Eugene Sh.
Mar 28 at 14:01
@Lundin Or.. they don't care?
– Eugene Sh.
Mar 28 at 14:01
Yes, it looks like the same bug but they wrote VS2015 produced correct output. On godbolt site you can try both of them and result is the same (memcpy call missing).
– oleque
Mar 28 at 14:12
Yes, it looks like the same bug but they wrote VS2015 produced correct output. On godbolt site you can try both of them and result is the same (memcpy call missing).
– oleque
Mar 28 at 14:12
fixed in an upcoming release Not sure if that means VS2019 or one of the VS2017 releases. I would not expect any older compiler to be fixed.
– drescherjm
Mar 28 at 14:15
fixed in an upcoming release Not sure if that means VS2019 or one of the VS2017 releases. I would not expect any older compiler to be fixed.
– drescherjm
Mar 28 at 14:15
|
show 1 more comment
What you do is perfectly legal, this is definitely a bug in 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; prevents the code generation bug.
Check it on Godbolt's Compiler Explorer.
add a comment
|
What you do is perfectly legal, this is definitely a bug in 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; prevents the code generation bug.
Check it on Godbolt's Compiler Explorer.
add a comment
|
What you do is perfectly legal, this is definitely a bug in 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; prevents the code generation bug.
Check it on Godbolt's Compiler Explorer.
What you do is perfectly legal, this is definitely a bug in 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; prevents the code generation bug.
Check it on Godbolt's Compiler Explorer.
edited Mar 29 at 22:42
answered Mar 28 at 20:33
chqrliechqrlie
69.2k9 gold badges60 silver badges116 bronze badges
69.2k9 gold badges60 silver badges116 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55398743%2fwhy-does-msvc-optimize-away-this-memcpy-call%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Is
extern char buffer[];legal?– NathanOliver
Mar 28 at 13:29
1
@Ctx right, but with either case
sizeof bufferdoesn't make much sense anyway.– Jabberwocky
Mar 28 at 13:33
1
I tried both C and C++: the result is the same. Initially it was C code. More details: the issue can be reproduced with MSVC 2005 and with modern compilers too (some of them you can check on godbolt.org).
– oleque
Mar 28 at 13:41
2
Well, C or C++ matters because C++ has a standard header called
memorybut C has no such thing, apart from I believe some non-standard Linux header. Maybe there's also some MS trash called memory.h? I can't find it in MSDN. What I'm getting at is that you haven't includedstring.hwhich is required for memcpy. VS, being barely compliant with C90 at best, might then go bananas and assume the prototype isint memcpy(int, int, int);because they probably don't follow C99 either. It's really hard to guess what this so-called "compiler" does and doesn't.– Lundin
Mar 28 at 13:46
2
extern char buffer[];is legal. Additionally it is nothing likeextern char *buffer;.– Antti Haapala
Mar 28 at 13:52