473,493 Members | 2,254 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

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 2097


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
2213
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
3599
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
3828
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
3677
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
4844
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
2295
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
5572
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
4584
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
3020
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
2020
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
6989
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7157
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7195
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
7367
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5453
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
4579
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3088
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3078
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1400
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

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.