Allocated memory

J

john

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.
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?
 
B

Barry Schwarz

Called this your statement 1.

There is no mention of a struct here.
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>>
 
R

Ravi Uday

[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;

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);
}
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, t->buf, t->size);
 
R

Ravi Uday

[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;

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);
}
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, t->buf, t->size);
Correction
printf("%d\n%p\n%d\n", t->one, (void *)t->buf, t->size);
 
B

Branimir Maksimovic

Ravi Uday said:
[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]).
Why do you need size to be 'volatile' ???

I'll explain later.
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.
I fail to understand what is the intention of this ??

illustration purpose
start of the function !!

not in c99. anyway one can declare it at the start.
t->one=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);
}
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, 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.:)
 
C

Chris Dollin

Branimir said:
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 ...
 
B

Branimir Maksimovic

Christian Bau said:
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
 
J

Joe Wright

Branimir said:
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.
 
C

Chris Torek

(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.]

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.
 
R

Ralmin

Branimir Maksimovic said:
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.
 
T

those who know me have no need of my name

[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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top