Hi,
In the following code fragment, gcc seems to ignore the initial value
assigned to pData. (compiled -fvolatile -O2 with gcc)
void test(void)
{
void *pData = (void*)0x3400;
pData = (void*)(*((unsigned char**)&pData) + 4);
memcpy(pData,(void*)0x1000,10);
return;
}
The generated code simply reads whatever garbage is at [sp], adds 4 to
that value, stores it back to [sp], and then calls memcpy.
I've found that, if I declare pData as
void * volatile pData = (void*)0x3400;
then the generated code behaves as I would expect -- that is, the value
actually passed to memcpy is 0x3404 because the initializer is not
optimized away.
I also found that, if I write this fragment this way..
void test(void)
{
void *pData = (void*)0x3400;
unsigned char *pChar;
pchar = pData;
pData = pChar + 4;
memcpy(pData,(void*)0x1000,10);
return;
}
then the generated code works as expected, passing 0x3404 to memcpy.
I know that the casts create temporary unnamed values, but I wouldn't
expect that to cause the complier to ignore the initializer.
It seems as though gcc doesn't consider the read access (&pData) when
deciding whether to optimize the initializer out of existence.
Does this make sense? Is a compiler allowed to ignore the code sequence
when read accesses are buried in a cast expression?
TIA,
GV 9 1431
On 27 Dec 2004 05:28:33 -0800, "gvarndell" <gv*******@hotmail.com>
wrote in comp.lang.c: Hi,
In the following code fragment, gcc seems to ignore the initial value assigned to pData. (compiled -fvolatile -O2 with gcc)
You're going to have to take this up with the compiler maintainers,
somewhere in the gnu group hierarchy.
void test(void) { void *pData = (void*)0x3400;
Initializing or assigning an integer value to a pointer type, with a
suitable cast, is legal but implementation-defined behavior.
pData = (void*)(*((unsigned char**)&pData) + 4);
Now you are attempting to use the value in pData as a valid pointer,
regardless of type. This is where the code crosses the line into
undefined behavior. The C standard places no requirements on the
result of this operation. Whether or not this code produces the
results you want is not a language issue.
memcpy(pData,(void*)0x1000,10); return; }
The generated code simply reads whatever garbage is at [sp], adds 4 to that value, stores it back to [sp], and then calls memcpy.
I've found that, if I declare pData as
void * volatile pData = (void*)0x3400;
then the generated code behaves as I would expect -- that is, the value actually passed to memcpy is 0x3404 because the initializer is not optimized away.
I also found that, if I write this fragment this way..
void test(void) { void *pData = (void*)0x3400; unsigned char *pChar;
pchar = pData; pData = pChar + 4; memcpy(pData,(void*)0x1000,10); return; }
then the generated code works as expected, passing 0x3404 to memcpy.
I know that the casts create temporary unnamed values, but I wouldn't expect that to cause the complier to ignore the initializer.
It seems as though gcc doesn't consider the read access (&pData) when deciding whether to optimize the initializer out of existence.
Does this make sense? Is a compiler allowed to ignore the code sequence when read accesses are buried in a cast expression?
Regardless of whether or not the compiler generates code that operates
as the compiler coders intended, you won't get any support for your
position here. Once your program produces undefined behavior, neither
ISO C nor this group take a position one way or the other.
Of course, your expression is unnecessarily convoluted.
pData = (void*)(*((unsigned char**)&pData) + 4);'
The first thing I would do is eliminate the unnecessary cast to
pointer to void. Then I'd eliminate & operator and the extra level of
indirection. I would write this expression, if I had to write it at
all, as:
pData = (unsigned char *)pData + 4;
....and let it go at that.
But you need to take this up with the GNU people.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
gvarndell <gv*******@hotmail.com> wrote: In the following code fragment, gcc seems to ignore the initial value assigned to pData. (compiled -fvolatile -O2 with gcc)
That's because you're lying to the compiler and it's getting its
revenge.
void test(void) { void *pData = (void*)0x3400;
pData = (void*)(*((unsigned char**)&pData) + 4);
Here's the lie -- you're telling the compiler to pretend that pData is
an unsigned char * rather than a void *. Instead of pretending, you
should just do a normal conversion:
pData = (unsigned char *)pData + 4;
Note that casting to void * is unnecessary (and, many would argue,
undesirable, unless you're actually writing C++ rather than C, in which
case it's required and your question is off-topic here).
-Larry Jones
I don't need to improve! Everyone ELSE does! -- Calvin
Thanks to you, and to Jack, for replying. The replies were helpful, but
don't get to the crux of my question -- which is my fault for framing
the question as a gcc question and supplying a convoluted example. So
I'd like to try again.
int test(void)
{
int a = 17;
a += 17;
return a;
}
If this function returned anything other than 34, the compiler would be
clearly broken.
int test(void)
{
int a = 17;
*((int *)&a) += 17;
return a;
}
Because of the fleeting nature of the values that result from casts,
I'm not so sure that any conforming C compiler would be to be blame if
this function returned 17 instead of the expected value of 34.
Wouldn't it be okay for any compiler to generate code that did this?
1. allocate storage for the integer variable 'a'
2. read an integer value from the address of 'a'
3. store whatever is read into a temporary
4. add 17 to the temporary and store the result in a temporary
5. store 17 into 'a' and return 'a'
I hope this clarifies my real question.
TIA
GV
gvarndell wrote: Thanks to you, and to Jack, for replying. The replies were helpful, but don't get to the crux of my question -- which is my fault for framing the question as a gcc question and supplying a convoluted example. So I'd like to try again.
int test(void) { int a = 17;
a += 17; return a; }
If this function returned anything other than 34, the compiler would be clearly broken.
int test(void) { int a = 17;
*((int *)&a) += 17;
&a has type int *, and points to an int object with the value 17.
The cast is from int * to int *, so it's a nop. And the & and *
cancel. So the expression resolves, effectively, to
a += 17;
Because of the fleeting nature of the values that result from casts, I'm not so sure that any conforming C compiler would be to be blame if this function returned 17 instead of the expected value of 34.
It would in fact be blameworthy. Wouldn't it be okay for any compiler to generate code that did this? 1. allocate storage for the integer variable 'a'
Yes.
2. read an integer value from the address of 'a'
Yes.
3. store whatever is read into a temporary
Yes.
4. add 17 to the temporary and store the result in a temporary
Yes.
5. store 17 into 'a' and return 'a'
No. The function must return the value 34.
"gvarndell" <gv*******@hotmail.com> wrote in message news:11**********************@z14g2000cwz.googlegr oups.com... Hi,
In the following code fragment, gcc seems to ignore the initial value assigned to pData. (compiled -fvolatile -O2 with gcc)
void test(void) { void *pData = (void*)0x3400;
pData = (void*)(*((unsigned char**)&pData) + 4); memcpy(pData,(void*)0x1000,10); return; }
The generated code simply reads whatever garbage is at [sp], adds 4 to that value, stores it back to [sp], and then calls memcpy.
The garbage at [sp] is pData.
pData is a local variant which is stored in the stack. And [sp] is the register
pointed to the stack. The compiler may also use [bp]/[ebp] to access it,
which is read-writeable. I've found that, if I declare pData as
void * volatile pData = (void*)0x3400;
then the generated code behaves as I would expect -- that is, the value actually passed to memcpy is 0x3404 because the initializer is not optimized away.
I also found that, if I write this fragment this way..
void test(void) { void *pData = (void*)0x3400; unsigned char *pChar;
pchar = pData; pData = pChar + 4; memcpy(pData,(void*)0x1000,10); return; }
then the generated code works as expected, passing 0x3404 to memcpy.
I know that the casts create temporary unnamed values, but I wouldn't expect that to cause the complier to ignore the initializer.
It seems as though gcc doesn't consider the read access (&pData) when deciding whether to optimize the initializer out of existence.
Does this make sense? Is a compiler allowed to ignore the code sequence when read accesses are buried in a cast expression?
TIA,
GV
gvarndell <gv*******@hotmail.com> wrote: int test(void) { int a = 17;
*((int *)&a) += 17; return a; }
Because of the fleeting nature of the values that result from casts, I'm not so sure that any conforming C compiler would be to be blame if this function returned 17 instead of the expected value of 34.
I am -- that code is perfectly well defined and any compiler that
doesn't return 34 is broken. Your original code contained type punning
that is *not* well defined and thus compilers are free to do whatever
they like with it.
-Larry Jones
Things are never quite as scary when you've got a best friend. -- Calvin la************@ugs.com wrote: gvarndell <gv*******@hotmail.com> wrote: int test(void) { int a = 17;
*((int *)&a) += 17; return a; }
Because of the fleeting nature of the values that result from
casts, I'm not so sure that any conforming C compiler would be to be blame
if this function returned 17 instead of the expected value of 34. I am -- that code is perfectly well defined and any compiler that doesn't return 34 is broken. Your original code contained type
punning that is *not* well defined and thus compilers are free to do whatever they like with it.
-Larry Jones
Thank you once again. This makes sense to me.
One final question on this, if I may.
Since this code
void test(void)
{
void *pData=(void*)0x3400;
(*(unsigned char**)&pData) += 4;
memcpy((unsigned char *)pData, (unsigned char *)0x1000,10);
return;
}
apparently causes undefined behavior, is a compiler required to at
least issue a warning about it?
I tried -pedantic with gcc and it doesn't make a peep about the code.
TIA,
GV
On 29 Dec 2004 09:29:28 -0800
"gvarndell" <gv*******@hotmail.com> wrote:
<snip> Thank you once again. This makes sense to me. One final question on this, if I may.
Since this code
void test(void) { void *pData=(void*)0x3400;
(*(unsigned char**)&pData) += 4; memcpy((unsigned char *)pData, (unsigned char *)0x1000,10); return; }
apparently causes undefined behavior, is a compiler required to at least issue a warning about it? I tried -pedantic with gcc and it doesn't make a peep about the code.
No. A compiler is not required to issue a warning for undefined
behaviour. One reason for this is that there are instances of undefined
behaviour that cannot be detected at compile time.
<OT>
gcc can give you warnings about some instances of undefined behaviour,
so it is well worth turning up the warnings. Something like "-ansi
-pedantic -Wall -O" might be useful. Others have different opinions
about the best set of options.
<OT>
However, always make sure you know *why* any given warning has been
produced before changing your code to remove it and never assume a
clean compile means correct code.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
In article <11*********************@z14g2000cwz.googlegroups. com>,
"gvarndell" <gv*******@hotmail.com> wrote: la************@ugs.com wrote: gvarndell <gv*******@hotmail.com> wrote: int test(void) { int a = 17;
*((int *)&a) += 17; return a; }
Because of the fleeting nature of the values that result from casts, I'm not so sure that any conforming C compiler would be to be blame if this function returned 17 instead of the expected value of 34.
I am -- that code is perfectly well defined and any compiler that doesn't return 34 is broken. Your original code contained type punning that is *not* well defined and thus compilers are free to do whatever they like with it.
-Larry Jones
Thank you once again. This makes sense to me. One final question on this, if I may.
Since this code
void test(void) { void *pData=(void*)0x3400;
(*(unsigned char**)&pData) += 4; memcpy((unsigned char *)pData, (unsigned char *)0x1000,10); return; }
apparently causes undefined behavior, is a compiler required to at least issue a warning about it? I tried -pedantic with gcc and it doesn't make a peep about the code.
"Warnings" are not part of the C language. Good compilers give warnings
in situations where you have written code that is legitimate C code but
looks to the compiler (which is written by experienced programmers) as
if you had unintentionally done something that you didn't actually want
to do.
The memcpy call most certainly doesn't look unintentionally. Whoever
wrote that code most certainly intenteded to write that code. Therefore,
no warning. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Jonathan Fielder |
last post by:
Hi,
My program (below) casts a double (which is in range for a float) to a
float. As far as I know this should give me the nearest representable
float, which will loose some precision. I...
|
by: Sacha Faust |
last post by:
I have an abstract class, RuleResponse, and then create a new class base on
it, RuleResponseSequence, and override the ++ operater.
If I try to cast a RuleResponse as a RuleResponseSequence and...
|
by: junky_fellow |
last post by:
Consider the following piece of code:
struct junk {
int i_val;
int i_val1;
char c_val;
};
int main(void)
{
|
by: Rajesh.S |
last post by:
some more info...
>-----Original Message-----
>I built a VC++.Net project as a dll and
>included it as a reference in a c# project.
>When I call a c++ function from the csharp
>project I get...
|
by: Philippe Bertrand |
last post by:
Is this a bug in the C# compiler or CLR runtime?
enum MyEnum { ZERO = 0, ONE = 1, TWO = 2 }
class Foo {
public Foo(string,object) { ... }
public Foo(string,MyEnum) { ... }
}
Foo f = new...
|
by: cyber citizen |
last post by:
Hi Folks,
We are encountering the following code issue on compiler susch as "xlc","gcc" but "icc" passes it successfully.
Sample code:
int main(void)
{
typedef unsigned char oratext;...
|
by: Charles Sullivan |
last post by:
I have a program written in C under Linux (gcc) which a user has
ported to run under AT&T SysV R4.
He sent me a copy of his makelog which displays a large number
of compiler warnings similar to...
|
by: erik.erikson |
last post by:
I am getting a compiler error that I can't well explain or even
understand the origin of (though I boiled it down close...). Below is
a bare-bones example.
What I am doing is defining the...
|
by: alertjean |
last post by:
Or may be I am stubborn or dumb ... of not putting in a * in the
typecast.
This is code I am worrying about
long long b=1;
int *address ;
address=(int)&b;
printf ("%x %x...
|
by: DolphinDB |
last post by:
Tired of spending countless mintues downsampling your data? Look no further!
In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
by: Shællîpôpï 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: af34tf |
last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
| |