473,324 Members | 2,456 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,324 software developers and data experts.

Allocated memory

I have a similar code to the following, here is the simplified version. I
didn't compile and run the following code, so don't worry about the syntax.
My question is I memcpy a larger data (10Byte) to a smaller one (1B),
however i can still access all the data (ref. to printf in the code). I
suppose the stack size is usually big enough for this to happen (tell me
otherwise). But what's the potential problem here?
I thought it might screw up the pointer, mStruct.buf. But it's not. Is this
legal? if not, why it's compliable? any problem here? thanks a lot.

char tenChars[10];
struct myStruct
{
int a;
char oneChar[1];
char * buf;
}

main()
{
struct myStruct mStruct;
char tenChar[10];

memset( tenChar, 1, 10);
memcpy( mStruct.oneChar, &tenChars, 10);
for (i=0; i<10; i++)
printf("%c\n", buf[i];
}
----------------------------------
remove "(n.o---s.p.a.m)" to reply


Jul 22 '05 #1
30 2087


john wrote:
I have a similar code to the following, here is the simplified version. I
didn't compile and run the following code, so don't worry about the syntax.
My question is I memcpy a larger data (10Byte) to a smaller one (1B),
however i can still access all the data (ref. to printf in the code). I
suppose the stack size is usually big enough for this to happen (tell me
otherwise). But what's the potential problem here?
I thought it might screw up the pointer, mStruct.buf. But it's not. Is this
legal? if not, why it's compliable? any problem here? thanks a lot.
In your example below, it is legal (see further note), but it's
exceedingly bad form and may not work on all compilers.

The reason this works is that myStruct is typically 12 bytes in size on
a 32-bit machine and 24 bits in size on a 64-bit machine. This is
structure padding. By aligning the fields in memory to match the machine
word size, considerable(?) performance is gained.

char tenChars[10];
struct myStruct
{
int a;
char oneChar[1];
char * buf;
}

main()
{
struct myStruct mStruct;
char tenChar[10];

memset( tenChar, 1, 10);
Change this to: strncpy( tenChar, "0123456789", 10);
memcpy( mStruct.oneChar, &tenChars, 10);
for (i=0; i<10; i++)
printf("%c\n", buf[i];
}

Now, printing mStruct.oneChar[0] should show you either 4, or 8,
depending upon your machine word size. Try the following (the results
will vary based upon the endian-ness of your machine):

printf( "%08x\n", mStruct.a ); // Should be something like 30313233
printf( "%08x\n", (unsigned) mStruct.buf ); // Should be like 383900??


----------------------------------
remove "(n.o---s.p.a.m)" to reply


Jul 22 '05 #2
"john" <john2000(n.o---s.p.a.m)@blueyonder.co.uk> wrote in message
news:%r*******************@front-1.news.blueyonder.co.uk...
I have a similar code to the following, here is the simplified version. I
didn't compile and run the following code, so don't worry about the syntax. My question is I memcpy a larger data (10Byte) to a smaller one (1B),
however i can still access all the data (ref. to printf in the code). I
suppose the stack size is usually big enough for this to happen (tell me
otherwise). But what's the potential problem here?
Your code writes past the end of mStruct.oneChar, which is undefined
behavior. On some systems it might work, but on my system it dumps core --
just like I expected.
I thought it might screw up the pointer, mStruct.buf. But it's not. Is this legal? if not, why it's compliable? any problem here? thanks a lot.
Just because it's undefined behavior doesn't mean it won't compile. Most C
translators will give you enough rope to hang yourself without so much as a
warning; taking care not to do so is _your_ responsibility, not the
translator's.
Various errors fixed below:
char tenChars[10];
struct myStruct
{
int a;
char oneChar[1];
char * buf;
}
};
main()
int main()
{
struct myStruct mStruct;
char tenChar[10];
int i;
memset( tenChar, 1, 10);
memcpy( mStruct.oneChar, &tenChars, 10);
for (i=0; i<10; i++)
printf("%c\n", buf[i];
printf("%c\n", mStruct.buf[i]);
}

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin

Jul 22 '05 #3
john wrote:
I have a similar code to the following, here is the simplified version. I
didn't compile and run the following code, so don't worry about the syntax.
My question is I memcpy a larger data (10Byte) to a smaller one (1B),
however i can still access all the data (ref. to printf in the code). I
suppose the stack size is usually big enough for this to happen (tell me
otherwise). But what's the potential problem here?


The problem is that you are moving data from a large container to
a very small container. Just as reality and physics state, you have
created undefined behavior. The container may overflow, it may break,
it may explode.

Why are you doing this?
--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #4
On Tue, 8 Jun 2004, john wrote:
I have a similar code to the following, here is the simplified version. I
didn't compile and run the following code, so don't worry about the syntax.
Why not take the few seconds to compile the code and try it. If it fails
to work then you don't even need to ask this question here. If it does
succeed then you can post code you know appears to be funcitonal.
My question is I memcpy a larger data (10Byte) to a smaller one (1B),
however i can still access all the data (ref. to printf in the code). I
suppose the stack size is usually big enough for this to happen (tell me
otherwise). But what's the potential problem here?
It is undefined behaviour. Anything can happen.
I thought it might screw up the pointer, mStruct.buf. But it's not. Is this
legal? if not, why it's compliable? any problem here? thanks a lot.
How do you know it is not trashing mStruct.buf? There is nothing in your
code example to show it is not.
char tenChars[10];
struct myStruct
{
int a;
char oneChar[1];
char * buf;
}

main()
{
struct myStruct mStruct;
char tenChar[10];

memset( tenChar, 1, 10);
memcpy( mStruct.oneChar, &tenChars, 10);
for (i=0; i<10; i++)
printf("%c\n", buf[i];
}


I'm unclear if you intended to create the global array tenChars and the
local array tenChar. It could be on your implementation that this excessive
allocation of memory is helping you. You are actually trashing the tenChar
memory.

I'm actually having to make assumptions about what you intended. I would
believe it safe to assume the reference to buf[i] should actually be
mStruct.buf[i]. I wonder why you are initializing tenChar with the memset
and then copying the contents of tenChars (an uninitialized array) to
mStruct.oneChar, using memcpy.

I created the following program that does compile:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char tenChars[] = "123456789";
struct myStruct {
int a;
char oneChar[1];
char *buf;
};

int main(void)
{
struct myStruct mStruct;
char tenChar[] = "123456789";

/* inialize the structure */
mStruct.a = 0xdead;
mStruct.buf = tenChar;
printf("a: %x\tbuf: %p\n", mStruct.a, mStruct.buf);

/* trash memory */
memcpy(mStruct.oneChar, tenChars, 10);

/* see that memory has been trashed */
printf("a: %x\tbuf: %p\n", mStruct.a, mStruct.buf);

return 0;
}

When I run it on my system, the value of mStruct.buf changes after the memcpy.
Dereferencing mStruct.buf after the memcpy will definitely cause undefined
behaviour. Since I have one instance that it fails to function as required,
I would never do something like this.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov
Jul 22 '05 #5
john posted:
I have a similar code to the following, here is the simplified version.
I didn't compile and run the following code, so don't worry about the
syntax. My question is I memcpy a larger data (10Byte) to a smaller one
(1B), however i can still access all the data (ref. to printf in the
code). I suppose the stack size is usually big enough for this to
happen (tell me otherwise). But what's the potential problem here?


int *pJack = 0x9983;

*pJack = 42;

-JKop
Jul 22 '05 #6
First of all, I found this from the software I'm working on. It's not
written by me, so do not ask me why I wrote this.
The code on the OP is just something I written from scratch to illustrate
the whole thing. I don't want to copy the exact code, because it's not
important and it might be distracting, and will be a long post (seems
unavoidable now :)). So do not tell me the correction of code like Stephen
and Darrell did. thanks anyway.

I did made a mistake in the code (maybe is this causing the confusion,
really sorry about that) which I intended to printf the oneChar instead of
buf on the last line. as follows:
printf("%c\n", mStruct.oneChar[i];
the purpose is to tell you that I can access all the data copied from
tenChar to oneChar. so the print out will be 10 ones as "1111111111".

I put char *buf just to illustrate this pointer has NOT been corrupted due
to stamping over by that "overflow copy". If I re-write it again, it will be
like this (the data vars before the main() are the same):

main()
{
struct myStruct mStruct;
char tenChar[10];
int d;

mStruct.buf = &d;
printf("%x\n", mStruct.buf); // let's say this will print "801a34bc"

memset( tenChar, 1, 10);
memcpy( mStruct.oneChar, &tenChars, 10);
for (i=0; i<10; i++)
printf("%c\n", mStruct.oneChar[i]; // this will print "1111111111"

printf("%x\n", mStruct.buf); // this will print "801a34bc"
}

As i said, I'm working for other people, and I can't tell them this is a bug
because it doesn't do anything wrong. so I need to know how I can generate a
fault with this, so that I can flag this as a bug and request a fix. that's
why I was asking what are the potential problems, as I can use these to
generate some faults. hopefully.

I will answer each post separately.

IMPORTANT BIT:
Remember the whole idea/point/question is copying a larger array to a
smaller one, what's potential problems?
give some examples or code so that i can reproduce, be it crashing, data
corruptions, whatever. Saying "undefine behaviour" is not what I lookin for,
because I know that.

"john" <john2000(n.o---s.p.a.m)@blueyonder.co.uk> wrote in message
news:%r*******************@front-1.news.blueyonder.co.uk...
I have a similar code to the following, here is the simplified version. I
didn't compile and run the following code, so don't worry about the syntax. My question is I memcpy a larger data (10Byte) to a smaller one (1B),
however i can still access all the data (ref. to printf in the code). I
suppose the stack size is usually big enough for this to happen (tell me
otherwise). But what's the potential problem here?
I thought it might screw up the pointer, mStruct.buf. But it's not. Is this legal? if not, why it's compliable? any problem here? thanks a lot.

char tenChars[10];
struct myStruct
{
int a;
char oneChar[1];
char * buf;
}

main()
{
struct myStruct mStruct;
char tenChar[10];

memset( tenChar, 1, 10);
memcpy( mStruct.oneChar, &tenChars, 10);
for (i=0; i<10; i++)
printf("%c\n", buf[i];
}
----------------------------------
remove "(n.o---s.p.a.m)" to reply


Jul 22 '05 #7
Please read my reply to the OP first!

"Thomas Matthews" <Th****************************@sbcglobal.net> wrote in
message news:1m*****************@newssvr15.news.prodigy.co m...
The problem is that you are moving data from a large container to
a very small container. Just as reality and physics state, you have
created undefined behavior. The container may overflow, it may break,
it may explode.
If you know the scenarios, criteria that can cause overflow, or break, or
explode in this case, that would be very helpful.
Why are you doing this?

As I explained earlier in my reply, I didn't do this, I found this. but it
didn't give me trouble, that troubles me :(

Jul 22 '05 #8
Please read my reply to the OP first!

"Tim Orbaker" <ti*@orb.aker.com> wrote in message
news:w9********************@wideopenwest.com...
In your example below, it is legal (see further note), but it's
exceedingly bad form and may not work on all compilers.
in this case, it works on mine
The reason this works is that myStruct is typically 12 bytes in size on
a 32-bit machine and 24 bits in size on a 64-bit machine. This is
structure padding. By aligning the fields in memory to match the machine
word size, considerable(?) performance is gained.
maybe it's a bad example, can you change the 10 bytes to 100 bytes, like
this:
char tenChars[100];
Please don't take this as a wind up, the actual code that I'm working on
copy more than 100 bytes. The reason I chose 10 bytes is no reason really,
mainly to simplify the code, and the whole point is to illustrate copying
from larger to smaller anyway.

Nevertheless, you have some interesting point there. I will try this out.
Why memcpy oneChar will override mStruct.a? because you said printf( "%08x\n", mStruct.a ); // Should be something like 30313233



char tenChars[10];
struct myStruct
{
int a;
char oneChar[1];
char * buf;
}

main()
{
struct myStruct mStruct;
char tenChar[10];

memset( tenChar, 1, 10);


Change this to: strncpy( tenChar, "0123456789", 10);
memcpy( mStruct.oneChar, &tenChars, 10);
for (i=0; i<10; i++)
printf("%c\n", buf[i];
}


Now, printing mStruct.oneChar[0] should show you either 4, or 8,
depending upon your machine word size. Try the following (the results
will vary based upon the endian-ness of your machine):

printf( "%08x\n", mStruct.a ); // Should be something like 30313233
printf( "%08x\n", (unsigned) mStruct.buf ); // Should be like 383900??


----------------------------------
remove "(n.o---s.p.a.m)" to reply



Jul 22 '05 #9
Please read my reply to the OP first!

"Stephen Sprunk" <st*****@sprunk.org> wrote in message
news:1f******************************@news.teranew s.com...
Your code writes past the end of mStruct.oneChar, which is undefined
behavior. On some systems it might work, but on my system it dumps core -- just like I expected.


what causing the core dump on your system? afaik, there are few criteria for
this, accessing a null pointer is on of them. I mean you should answer only
if you know, it's a bit too difficullt job to find out anyway.


Jul 22 '05 #10
Please read my reply to the OP first!

"Darrell Grainger" <da*****@NOMORESPAMcs.utoronto.ca.com> wrote in message
news:Pi*******************************@drj.pf...
On Tue, 8 Jun 2004, john wrote:

Why not take the few seconds to compile the code and try it. If it fails
to work then you don't even need to ask this question here. If it does
succeed then you can post code you know appears to be funcitonal.
Hope you understand now. the code written here is not important. The actual
code compiled and runs ok (maybe it's not ok, this is what I'm trying to
find out).
It is undefined behaviour. Anything can happen.
If you can give some examples that you know of, that would be great.
How do you know it is not trashing mStruct.buf? There is nothing in your
code example to show it is not.
I should printf the "buf" in the code to clarify this.
I'm unclear if you intended to create the global array tenChars and the
local array tenChar. It could be on your implementation that this excessive allocation of memory is helping you. You are actually trashing the tenChar
memory.
Oh, this is new to me. I will read the rest first.... now I have read the
rest. but I still dont get it as how tenChar will get trashed. Will run the
code and see.
I'm actually having to make assumptions about what you intended. I would
believe it safe to assume the reference to buf[i] should actually be
mStruct.buf[i]. correct assumption. But this is a mistake, I actually want to print
mStruct.oneChar to illustrate I can access all the copied data.
I wonder why you are initializing tenChar with the memset
and then copying the contents of tenChars (an uninitialized array) to
mStruct.oneChar, using memcpy.
just to prove I can access all the copied data, so the print out will be
"1111111111".
I created the following program that does compile:
no need for this, as it's only for illustration.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char tenChars[] = "123456789";
struct myStruct {
int a;
char oneChar[1];
char *buf;
};

int main(void)
{
struct myStruct mStruct;
char tenChar[] = "123456789";

/* inialize the structure */
mStruct.a = 0xdead;
mStruct.buf = tenChar;
printf("a: %x\tbuf: %p\n", mStruct.a, mStruct.buf);

/* trash memory */
memcpy(mStruct.oneChar, tenChars, 10);

/* see that memory has been trashed */
printf("a: %x\tbuf: %p\n", mStruct.a, mStruct.buf);

return 0;
}

When I run it on my system, the value of mStruct.buf changes after the memcpy. Dereferencing mStruct.buf after the memcpy will definitely cause undefined
behaviour. Since I have one instance that it fails to function as required, I would never do something like this.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov


Jul 22 '05 #11
"john" <john2000(n.o---s.p.a.m)@blueyonder.co.uk> wrote in message
news:Ye*******************@front-1.news.blueyonder.co.uk...
Please read my reply to the OP first!

"Stephen Sprunk" <st*****@sprunk.org> wrote in message
news:1f******************************@news.teranew s.com...
Your code writes past the end of mStruct.oneChar, which is undefined
behavior. On some systems it might work, but on my system it dumps
core -- just like I expected.
what causing the core dump on your system? afaik, there are few criteria

for this, accessing a null pointer is on of them. I mean you should answer only if you know, it's a bit too difficullt job to find out anyway.


When memcpy() writes past the end of mStruct.oneChar, it overwrites
mStruct.buf with 0x01010101. When main() tries to dereference
mStruct.buf[i] to generate the argument to printf(), it accesses memory that
doesn't belong to the process and thus triggers a segfault. This is just my
analysis from reading the code, but I'll go through it with gdb if you want
proof for your employer.

My particular system is Linux 2.2.16 and gcc 2.91.66, but I'm surprised this
isn't the result on every system with memory protection. In any case, it
does invoke undefined behavior and should be considered a bug even if it
mysteriously works on some systems.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin

Jul 22 '05 #12
On Thu, 10 Jun 2004 00:42:24 +0100, "john"
<john2000(n.o---s.p.a.m)@blueyonder.co.uk> wrote:
First of all, I found this from the software I'm working on. It's not
written by me, so do not ask me why I wrote this.
The code on the OP is just something I written from scratch to illustrate
the whole thing. I don't want to copy the exact code, because it's not
important and it might be distracting, and will be a long post (seems
unavoidable now :)). So do not tell me the correction of code like Stephen
and Darrell did. thanks anyway.

I did made a mistake in the code (maybe is this causing the confusion,
really sorry about that) which I intended to printf the oneChar instead of
buf on the last line. as follows:
printf("%c\n", mStruct.oneChar[i];
the purpose is to tell you that I can access all the data copied from
tenChar to oneChar. so the print out will be 10 ones as "1111111111".

I put char *buf just to illustrate this pointer has NOT been corrupted due
to stamping over by that "overflow copy". If I re-write it again, it will be
like this (the data vars before the main() are the same):

main()
int main(void)
{
struct myStruct mStruct;
char tenChar[10];
int d;

mStruct.buf = &d;
printf("%x\n", mStruct.buf); // let's say this will print "801a34bc"
Let's not. Most of us prefer not to depend on undefined behavior. %x
expects an int. You are passing it a pointer. If you want to print
the value of a pointer, use %p and cast the value to void*.

memset( tenChar, 1, 10);
memcpy( mStruct.oneChar, &tenChars, 10);
Since memcpy takes pointers to void, the use of &tenChars doesn't hurt
here but you really want to get in the habit of using the array name
without an & in most situations like this. While you are at it,
decide if the array name is tenChar or tenChars.
for (i=0; i<10; i++)
i is undefined.
printf("%c\n", mStruct.oneChar[i]; // this will print "1111111111"
Not very likely. Did you try it? Each oneChar[i] has the value
integer 1. This is considerably different than the character value
'1' which is what it would have to contain to match your comment.

By the way, why do you think the \n will not force each character to a
new line?

printf("%x\n", mStruct.buf); // this will print "801a34bc"
}

As i said, I'm working for other people, and I can't tell them this is a bug
because it doesn't do anything wrong. so I need to know how I can generate a
It doesn't work now. How many more faults do you need?
fault with this, so that I can flag this as a bug and request a fix. that's
why I was asking what are the potential problems, as I can use these to
generate some faults. hopefully.

I will answer each post separately.

IMPORTANT BIT:
Remember the whole idea/point/question is copying a larger array to a
smaller one, what's potential problems?
Tell them to look at every virus they have ever relieved. Most
exploit some kind of buffer overrun, which is exactly what copying a
large array to a small one is.
give some examples or code so that i can reproduce, be it crashing, data
corruptions, whatever. Saying "undefine behaviour" is not what I lookin for,
because I know that.

"john" <john2000(n.o---s.p.a.m)@blueyonder.co.uk> wrote in message
news:%r*******************@front-1.news.blueyonder.co.uk...
I have a similar code to the following, here is the simplified version. I
didn't compile and run the following code, so don't worry about the

syntax.
My question is I memcpy a larger data (10Byte) to a smaller one (1B),
however i can still access all the data (ref. to printf in the code). I
suppose the stack size is usually big enough for this to happen (tell me
otherwise). But what's the potential problem here?
If you really want to be able to show them that it is broken, have
them look at the generated assembler code. If they can't read that,
then you do it and define several more variables so that some
immediately follow the short array. Initialize one of these post
array variables, print it, copy the long array to the short, then
print the post array variable again and show them the changed value.

You might also want to work on your resume since this head in the sand
style of management will not survive in the long run. Remember the
adage "those who wait for an accident before fixing anything are part
of the problem, not part of the solution."
I thought it might screw up the pointer, mStruct.buf. But it's not. Is

this


You have no idea how much padding the compiler decided to insert
between oneChar and buf.

On my system when I ran your code, buf printed two different values:
65fddc and 1010101. It did exactly what you expected. Why it doesn't
on your system is something only you can determine.
legal? if not, why it's compliable? any problem here? thanks a lot.
You have the same problems copying the large array into the smaller
one not defining i. Then you try to dereference buf when it was never
initialized.

I think there used to be a contest here about who could cram the most
undefined behavior into the shortest code. I don't think you are near
the record but if you practice...

char tenChars[10];
struct myStruct
{
int a;
char oneChar[1];
char * buf;
}

main()
{
struct myStruct mStruct;
char tenChar[10];

memset( tenChar, 1, 10);
memcpy( mStruct.oneChar, &tenChars, 10);
for (i=0; i<10; i++)
printf("%c\n", buf[i];
}


<<Remove the del for email>>
Jul 22 '05 #13
In article <%d*******************@front-1.news.blueyonder.co.uk>
john <john2000(n.o---s.p.a.m)@blueyonder.co.uk> writes:
The code [in my original post] is just something I written from
scratch to illustrate the whole thing. I don't want to copy the
exact code, because it's not important and it might be distracting,
and will be a long post ... I did made a mistake in the [original example posting] code

[followed by a new example that does not compile and clearly
is not the problematic code].

I think this deserves a parable. :-)

A man showed up at a veterinary office with a Persian house cat.
"My pet is sick, can you help him?"

The doctor examined the cat and told the man that the problem was
simply a hairball, and that grooming and petromalt would typically
solve the problem.

"Oh no," the man exclaimed. "The problem isn't hairballs!"

"I think it is," replied the vet. "This cat has no fever, and
no signs of anything other than mild dehydration."

"But you see," explained the main, "this isn't even my pet -- I
have an elephant! I didn't bring him in because he's too big to
fit in my car!"
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 22 '05 #14
"john" <john2000(n.o---s.p.a.m)@blueyonder.co.uk> wrote in message news:<%d*******************@front-1.news.blueyonder.co.uk>...
IMPORTANT BIT:
Remember the whole idea/point/question is copying a larger array to a
smaller one, what's potential problems?
give some examples or code so that i can reproduce, be it crashing, data
corruptions, whatever. Saying "undefine behaviour" is not what I lookin for,
because I know that.

Just explain behavior of following program :
include <stdio.h>

typedef struct Test{
int one[1];
volatile int size;
int* buf;
} Test;

void initTest(Test* t, int size)
{
t->size = size;
t->buf = t->one;
for(int i=0;i<t->size;++i)t->one[i]=i;
}

void printTest(Test* t)
{
for(int i = 0; i<t->size; ++i)
{
printf("%d\n",t->one[i]);
}
printf("%p %p %d\n",(void*)t->one,(void*)t->buf,t->size);
}

int main(void)
{
Test t;
initTest(&t, 1000);
printTest(&t);
return 0;
}

Greetings, Bane.
Jul 22 '05 #15
Branimir Maksimovic wrote:
.... snip ...
Just explain behavior of following program :
include <stdio.h>

.... snip code ...

There is no explanation. It exhibits undefined behaviour, so it
can do anything at all, including committing rape, arson, battery,
and lies.

Do not post C to c.l.c++, nor C++ to c.l.c.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Jul 22 '05 #16
CBFalconer wrote:

There is no explanation. It exhibits undefined behaviour, so it
can do anything at all, including committing rape, arson, battery,
and lies.


I'm sorry. Discussion of MSVC++ is off-topic here. ;-)

Alan
Jul 22 '05 #17
Actually you didn't tell the whole story, the more complete story is as
followed:

Before this man went to the vet with his cat. He actually did bring his
elephant to lots of vet clinics. but he always get refused. Those vets don't
even want to entertain him, just told this man we don't take elephants.

"Chris Torek" <no****@torek.net> wrote in message
news:ca********@news3.newsguy.com...
In article <%d*******************@front-1.news.blueyonder.co.uk>
john <john2000(n.o---s.p.a.m)@blueyonder.co.uk> writes:
The code [in my original post] is just something I written from
scratch to illustrate the whole thing. I don't want to copy the
exact code, because it's not important and it might be distracting,
and will be a long post ...

I did made a mistake in the [original example posting] code

[followed by a new example that does not compile and clearly
is not the problematic code].

I think this deserves a parable. :-)

A man showed up at a veterinary office with a Persian house cat.
"My pet is sick, can you help him?"

The doctor examined the cat and told the man that the problem was
simply a hairball, and that grooming and petromalt would typically
solve the problem.

"Oh no," the man exclaimed. "The problem isn't hairballs!"

"I think it is," replied the vet. "This cat has no fever, and
no signs of anything other than mild dehydration."

"But you see," explained the main, "this isn't even my pet -- I
have an elephant! I didn't bring him in because he's too big to
fit in my car!"
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to

spammers.
Jul 22 '05 #18

"CBFalconer" <cb********@yahoo.com> wrote in message
news:40***************@yahoo.com...
Branimir Maksimovic wrote:
... snip ...

Just explain behavior of following program :
include <stdio.h>

... snip code ...

There is no explanation. It exhibits undefined behaviour, so it
can do anything at all, including committing rape, arson, battery,
and lies.


Yes it is undefined behavior, but... we can assume that
arrays in C and C++ are laid in memory contiguously.
Variable of type "volatile int", follows array of int,
so we can assume that compiler will include side effect of buffer
overrunning, resulting that value in *that* variable, will be visible
in for loop (not cached), so program will not crash.:)
How's that different from struct hacks which are widely spread
around the globe?

typedef struct Hack{
// some elements
char string[1];
} Hack;

.....
const char* tmp = "Some thing";
Hack* pHack = malloc(sizeof(Hack)+strlen(tmp));
strcpy(pHack->string,tmp);
.....

Do not post C to c.l.c++, nor C++ to c.l.c.

I thought that program will compile fine with both c++ and c99
compilers. :) which part (of snipped code)is not C or C++?

Greetings, Bane.
P.S. this is just counter example, that is undefined behavior that
"works". Perhaps OP's example is similar to struct hack but
he haven't posted (or didn't understand) actual code.

Jul 22 '05 #19
In article <ca**********@news.eunet.yu>,
"Branimir Maksimovic" <bm***@eunet.yu> wrote:
"CBFalconer" <cb********@yahoo.com> wrote in message
news:40***************@yahoo.com...
Branimir Maksimovic wrote:

... snip ...

Just explain behavior of following program :
include <stdio.h>

... snip code ...

There is no explanation. It exhibits undefined behaviour, so it
can do anything at all, including committing rape, arson, battery,
and lies.


Yes it is undefined behavior, but... we can assume that
arrays in C and C++ are laid in memory contiguously.
Variable of type "volatile int", follows array of int,
so we can assume that compiler will include side effect of buffer
overrunning, resulting that value in *that* variable, will be visible
in for loop (not cached), so program will not crash.:)
How's that different from struct hacks which are widely spread
around the globe?

typedef struct Hack{
// some elements
char string[1];
} Hack;

....
const char* tmp = "Some thing";
Hack* pHack = malloc(sizeof(Hack)+strlen(tmp));
strcpy(pHack->string,tmp);
....

Do not post C to c.l.c++, nor C++ to c.l.c.

I thought that program will compile fine with both c++ and c99
compilers. :) which part (of snipped code)is not C or C++?

Greetings, Bane.
P.S. this is just counter example, that is undefined behavior that
"works". Perhaps OP's example is similar to struct hack but
he haven't posted (or didn't understand) actual code.


A good optimizing compiler will produce the same code for

strcpy (pHack->string, tmp);
and for
pHack->string[0] = '\0';

strcpy (pHack->string, tmp) has undefined behavior except if tmp points
to an empty string. The compiler can assume that there is no undefined
behavior and therefore tmp points to an empty string. If tmp points to
an empty string, then strcpy will just set the first array element to
'\0'. Therefore both statements are equivalent.
Jul 22 '05 #20

"Barry Schwarz" <sc******@deloz.net> wrote in message
news:ca**********@216.39.143.94...
<snip>
then you do it and define several more variables so that some
immediately follow the short array. Initialize one of these post
array variables, print it, copy the long array to the short, then
print the post array variable again and show them the changed value.


Called this your statement 1.
I thought it might screw up the pointer, mStruct.buf. But it's not. Is
this


You have no idea how much padding the compiler decided to insert
between oneChar and buf.


And this is statement 2

Sorry I didn't get this because the statement 2 is contradicted to statement
1. So which one do you want to scrap and keep the other one?
Jul 22 '05 #21
On Fri, 11 Jun 2004 01:33:25 +0100, "john"
<john2000(n.o---s.p.a.m)@blueyonder.co.uk> wrote:

"Barry Schwarz" <sc******@deloz.net> wrote in message
news:ca**********@216.39.143.94...
<snip>
then you do it and define several more variables so that some
immediately follow the short array. Initialize one of these post
array variables, print it, copy the long array to the short, then
print the post array variable again and show them the changed value.
Called this your statement 1.


There is no mention of a struct here.
> I thought it might screw up the pointer, mStruct.buf. But it's not. Is
>this
You have no idea how much padding the compiler decided to insert
between oneChar and buf.


And this is statement 2


Padding is unique to structs.

Sorry I didn't get this because the statement 2 is contradicted to statement
1. So which one do you want to scrap and keep the other one?


Statement 1 was not meant to imply that your short array should be in
a struct.

<<Remove the del for email>>
Jul 22 '05 #22
[snip]

See explanations inline..
Just explain behavior of following program :
include <stdio.h>

typedef struct Test{
int one[1];
You have space for 2 integer values - one[0] and one[1]
volatile int size;
Why do you need size to be 'volatile' ???
int* buf;
Mind you buff is not initialized. } Test;

void initTest(Test* t, int size)
{
t->size = size;
t->buf = t->one;
I fail to understand what is the intention of this ??
for(int i=0;i<t->size;++i)--> int i -> needs to be declared at the start of the function !! t->one[i]=i;

You have passed 1000 as the size !!! t->one is array of 2 int elements.
Where do you think the space is for remaining elements ??
You have just invoked 'Undefined behaviour'. Check your pants..before
continuing !!!!!! }

void printTest(Test* t)
{
for(int i = 0; i<t->size; ++i)
{
printf("%d\n",t->one[i]);
}
printf("%p %p %d\n",(void*)t->one,(void*)t->buf,t->size);
Why use %p ??? If you need the see the values just use
printf("%d\n%s\n%d\n", t->one[i], t->buf, t->size);
}

int main(void)
{
Test t;
initTest(&t, 1000);
printTest(&t);
return 0;
}

Greetings, Bane.

Jul 22 '05 #23
[snip]

See explanations inline..
Just explain behavior of following program :
include <stdio.h>

typedef struct Test{
int one[1];
You have space for 2 integer values - one[0] and one[1]
volatile int size;
Why do you need size to be 'volatile' ???
int* buf;
Mind you buff is not initialized. } Test;

void initTest(Test* t, int size)
{
t->size = size;
t->buf = t->one;
I fail to understand what is the intention of this ??
for(int i=0;i<t->size;++i)--> int i -> needs to be declared at the start of the function !! t->one[i]=i;

You have passed 1000 as the size !!! t->one is array of 2 int elements.
Where do you think the space is for remaining elements ?? }

void printTest(Test* t)
{
for(int i = 0; i<t->size; ++i)
{
printf("%d\n",t->one[i]);
}
printf("%p %p %d\n",(void*)t->one,(void*)t->buf,t->size);
Why use %p ??? If you need the see the values just use
printf("%d\n%s\n%d\n", t->one[i], t->buf, t->size);
Correction
printf("%d\n%p\n%d\n", t->one[i], (void *)t->buf, t->size);

}

int main(void)
{
Test t;
initTest(&t, 1000);
printTest(&t);
return 0;
}

Greetings, Bane.

Jul 22 '05 #24

"Ravi Uday" <ra*****@yahoo.com> wrote in message
news:ec**************************@posting.google.c om...
[snip]

See explanations inline..
Just explain behavior of following program :
include <stdio.h>

typedef struct Test{
int one[1];
You have space for 2 integer values - one[0] and one[1]


No. Just check sizeof(one)/sizeof(one[0]).
volatile int size;
Why do you need size to be 'volatile' ???


I'll explain later.
int* buf;
Mind you buff is not initialized.

Will be later, this is not Java.
I use it just for illustration that buf will not be overwritten.
} Test;

void initTest(Test* t, int size)
{
t->size = size;
t->buf = t->one;


I fail to understand what is the intention of this ??


illustration purpose
for(int i=0;i<t->size;++i)--> int i -> needs to be declared at the start of the function !!

not in c99. anyway one can declare it at the start.
t->one[i]=i;

You have passed 1000 as the size !!! t->one is array of 2 int elements. Where do you think the space is for remaining elements ??
You have just invoked 'Undefined behaviour'. Check your pants..before continuing !!!!!!


well :) but... memory layout looks like this:

int one[0]
int size
int* buf

in first iteration one[0] will be set to 0;
then ++i gives i==1; then 1<1000 evaluates to true;
then one[1] = 1 ;this is buffer overwrite, but exactly over
size (both ints, no padding hopefully :)); size is now 1;
then ++i gives i == 2; then 2<1 evaluates to false.
Here is the point why size is volatile.
If size weren't volatile compiler would cache it in
register and program will crash :)
}

void printTest(Test* t)
{
for(int i = 0; i<t->size; ++i)
{
printf("%d\n",t->one[i]);
}
printf("%p %p %d\n",(void*)t->one,(void*)t->buf,t->size);


Why use %p ??? If you need the see the values just use
printf("%d\n%s\n%d\n", t->one[i], t->buf, t->size);

I want't to show that buf is not overwriten, that is has same
value as t->one;anyway t->buf is pointer to int.

Greetings, Bane.

P.S.
I can imagine (theoretically), that there are implementations where this
would not work. For example where there are extra padding
bytes between one and size, or where volatile would
not prevent caching, but unlikely.
Don't take all this to harshly cause this thread is all about ub.:)

Jul 22 '05 #25
Branimir Maksimovic wrote:
well :) but... memory layout looks like this:

int one[0]
int size
int* buf
You mean, "*if* the memory layout looks like this".
P.S.
I can imagine (theoretically), that there are implementations where this
would not work. For example where there are extra padding
bytes between one and size, or where volatile would
not prevent caching, but unlikely.


Re-ordering the declarations sounds eminently plausible, though;
especially if you renamed /size/ to /count/ or /limit/ ...

And I can certainly imagine an implementation where each top-level
object was allocated in a separate segment ...

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html
Jul 22 '05 #26
Christian Bau <ch***********@cbau.freeserve.co.uk> wrote in message news:<ch*********************************@slb-newsm1.svr.pol.co.uk>...
.............

A good optimizing compiler will produce the same code for

strcpy (pHack->string, tmp);
and for
pHack->string[0] = '\0';

strcpy (pHack->string, tmp) has undefined behavior except if tmp points
to an empty string. The compiler can assume that there is no undefined
behavior and therefore tmp points to an empty string. If tmp points to
an empty string, then strcpy will just set the first array element to
'\0'. Therefore both statements are equivalent.


Hm. So that's why C now has posibility for incomplete arrays in structs?

typedef struct LegalHack{
// some elements
char string[]; // only valid in C :(
} LegalHack;
....
const char* tmp = "something";
LegalHack* pHack = malloc(sizeof(LegalHack)+strlen(tmp)+1);
strcpy(pHack->string, tmp);
....

I guess now there is no ub?

Greetings, Bane.

P.S. fortunatelly g++ supports this as an extension
Jul 22 '05 #27
Branimir Maksimovic wrote:
"CBFalconer" <cb********@yahoo.com> wrote in message
news:40***************@yahoo.com...
Branimir Maksimovic wrote:

... snip ...

Do not post C to c.l.c++, nor C++ to c.l.c.


I thought that program will compile fine with both c++ and c99
compilers. :) which part (of snipped code)is not C or C++?


We're a little touchy. In comp.lang.c We concern ourselves C and not
C++. We don't know or care about C++.

In comp.lang.c++ They care about C++. To the extent that C code can
be accepted by the C++ compiler They seem pleased.

We don't have this problem. C++ code is a syntax error at best or
Undefined Behavior in C.

--
Joe Wright mailto:jo********@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jul 22 '05 #28
(Note: any analogy -- and this is one -- will fall over if pushed too
far, but I think we can push this one one more step...)

[Top-posting rearranged by the expedient of snipping my "parable",
in which someone brings a cat into the vet, instead of the sick
elephant, because the elephant physically can't be brought in.]

In article <news:dE*******************@front-1.news.blueyonder.co.uk>
john <john2000(n.o---s.p.a.m)@blueyonder.co.uk> writes:
Actually you didn't tell the whole story, the more complete story is as
followed:

Before this man went to the vet with his cat. He actually did bring his
elephant to lots of vet clinics. but he always get refused. Those vets don't
even want to entertain him, just told this man we don't take elephants.


In this case the "elephant" stands for the original code, which
presumably has a real problem, but is too unweildy for a newsgroup
posting.

You are in an untenable position, and I am not unsympathetic. But
a complete solution is not going to be found here. To pursue the
analogy, you may need a different vet, probably a specialist who
will do "house calls". Chances are that you will have to pay him
or her. (In reality, bring in a consultant -- there should be a
number of competent consultants for hire these days, although
finding one nearby might not be all that easy either.)

Another approach would be to "go to vet school" yourself: hang out
in comp.lang.c for a few years and learn what is strictly conforming
/ 100% portable ("chemistry and biology", as it were), and also in
system-specific groups as needed ("elephant anatomy and physiology").
Eventually, you can become the specialist you seek.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 22 '05 #29
"Branimir Maksimovic" <bm***@volomp.com> wrote:
Hm. So that's why C now has posibility for incomplete arrays in structs?
Only C99, which is not the version of C that is implemented by most
compilers.

(Code reformed into an almost-valid program)

#include <stdlib.h>
#include <string.h>

int main(void)
{
typedef struct LegalHack {
// some elements
char string[]; // only valid in C :(
} LegalHack;

const char *tmp = "something";
LegalHack *pHack = malloc(sizeof(LegalHack) + strlen(tmp) + 1);
if(pHack)
strcpy(pHack->string, tmp);
free(pHack);
return 0;
}
I guess now there is no ub?
So long as there are some elements to replace your comment of that name. It
is an error to have just a flexible array member in an otherwise empty
struct.
P.S. fortunatelly g++ supports this as an extension


P.S. gcc supports it as a natural part of the -std=c99 option.

--
Simon.
Jul 22 '05 #30
[fu-t set]

in comp.lang.c i read:
P.S. gcc supports it as a natural part of the -std=c99 option.


which itself is only partly supported. for further gcc only discussion i
suggest using the gcc mailing lists.

--
a signature
Jul 22 '05 #31

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Kjell Arne Johansen | last post by:
Hi How does it work? //This works //Constructor is run and memory allocated for m_AnObject CSomeClass SomeClass1; //copying data works fine SomeClass1 = SomeClass2;
3
by: Tony Johansson | last post by:
Hello Experts!! When you instansiate varaibles(object) you can do so in four different scops which are. Within a block which is called Local or block scope . Within a function which is called...
4
by: Thomas Paul Diffenbach | last post by:
Can anyone point me to an open source library of /statically allocated/ data structures? I'm writing some code that would benefit from trees, preferably self balancing, but on an embedded system...
31
by: bilbothebagginsbab5 AT freenet DOT de | last post by:
Hello, hello. So. I've read what I could find on google(groups) for this, also the faq of comp.lang.c. But still I do not understand why there is not standard method to "(...) query the...
16
by: Ankit Raizada | last post by:
Is there a way to know how much memory has being allocated(dynamically) to a pointer. Related to this, can we find out has a pointer already been freed? I am using VC++
6
by: lovecreatesbeauty | last post by:
Hello experts, 1. Does C guarantee the data layout of the memory allocated by malloc function on the heap. I mean, for example, if I allocate a array of 100 elements of structure, can I always...
5
by: nmtoan | last post by:
Hi, I could not find any answer to this simple question of mine. Suppose I have to write a program, the main parts of it are as follows: #include <blahblah.h> struct {
74
by: ballpointpenthief | last post by:
If I have malloc()'ed a pointer and want to read from it as if it were an array, I need to know that I won't be reading past the last index. If this is a pointer to a pointer, a common technique...
26
by: Bill Reid | last post by:
Bear with me, as I am not a "professional" programmer, but I was working on part of program that reads parts of four text files into a buffer which I re-allocate the size as I read each file. I...
6
by: Praetorian | last post by:
This is actually 2 questions: The first one: I have a function (FuncA) calling another (FuncB) with a set of parameters which also includes an int * initialized to NULL before the call. Now...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
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...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
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...
0
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...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
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 using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.