473,385 Members | 1,676 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,385 software developers and data experts.

Variable length arrays


If a VLA appears within a loop body, it seems the behavior is
different with two different compilers I tried. I looked at the
standard text, but couldn't find a definite answer there either.

Consider the following test program

/* begin foo.c */
#include <stdio.h>
#include <string.h>

void test(int n, size_t size)
{
int i;

for(i = 0; i < n; i++) {
unsigned char vla[size];
memset(vla, (i & 255), size);
printf("step %d: vla=%p\n", i, &vla[0]);
}
}

int main(void)
{
test(10, 256*1024L);
return 0;
}
/* end foo.c */

With gcc, 'vla' is reused in every iteration, i.e., the address
of 'vla[0]' is identical in every step.

However, with lcc-win32, output is as follows...

step 0: vla=0x002ffea0
step 1: vla=0x002bfea0
step 2: vla=0x0027fea0
step 3: vla=0x0023fea0
[*CRASH*]

, meaning, new storage is allocated for 'vla' at every iteration,
eventually exhausting all available auto storage.

Now, is this just implementation dependant and this kind of construct
should be avoided, or is one of these compilers not working correctly?

Should a bug report be filed?

Thanks
--
Erwin Lindemann
Mar 6 '08 #1
37 2108
On Thu, 6 Mar 2008 02:38:17 +0100 (CET), Erwin Lindemann
<el******@wupp.invalidwrote in comp.lang.c:
>
If a VLA appears within a loop body, it seems the behavior is
different with two different compilers I tried. I looked at the
standard text, but couldn't find a definite answer there either.
There is no definitive answer. All the standard says about VLAs that
might be relevant is this:

"For such an object that does have a variable length array type, its
lifetime extends from the declaration of the object until execution of
the program leaves the scope of the declaration. If the scope is
entered recursively, a new instance of the object is created each
time. The initial value of the object is indeterminate."

It says nothing at all about whether each creation must, may, or may
not have the same address. So it is entirely a QOI issue.
Consider the following test program

/* begin foo.c */
#include <stdio.h>
#include <string.h>

void test(int n, size_t size)
{
int i;

for(i = 0; i < n; i++) {
unsigned char vla[size];
memset(vla, (i & 255), size);
printf("step %d: vla=%p\n", i, &vla[0]);
}
}

int main(void)
{
test(10, 256*1024L);
return 0;
}
/* end foo.c */

With gcc, 'vla' is reused in every iteration, i.e., the address
of 'vla[0]' is identical in every step.

However, with lcc-win32, output is as follows...

step 0: vla=0x002ffea0
step 1: vla=0x002bfea0
step 2: vla=0x0027fea0
step 3: vla=0x0023fea0
[*CRASH*]

, meaning, new storage is allocated for 'vla' at every iteration,
eventually exhausting all available auto storage.

Now, is this just implementation dependant and this kind of construct
should be avoided, or is one of these compilers not working correctly?
Since the standard does not require either behavior, it is not a
conformance defect that I can see. It is a QOI issue, and I suggest
you contact the offending compiler's implementer, either directly or
on his support group.
Should a bug report be filed?
Since the standard does not guarantee that the creation of any array
of automatic duration will succeed, even if it is not a VLA, it's hard
to see a complaint on standard conformance grounds, but it's a huge
QOI issue.

I'd complain if I used this feature of his compiler, although I have
plonked him and don't use his compiler at all anymore.

Consider a similar case:

#include <stdio.h>

void func(int x)
{
printf("%p\n", (void *)&x;
}

int main(void)
{
int x = 0;
func();
func();
func();
return x;
}

I don't think I have ever used an implementation where the three calls
to func() would output different values.

Do you think the C standard requires it to be the same? If not, do
you think it should?

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Mar 6 '08 #2
Erwin Lindemann <el******@wupp.invalidwrites:
With gcc, 'vla' is reused in every iteration, i.e., the address
of 'vla[0]' is identical in every step.

However, with lcc-win32, output is as follows...

step 0: vla=0x002ffea0
step 1: vla=0x002bfea0
step 2: vla=0x0027fea0
step 3: vla=0x0023fea0
[*CRASH*]

, meaning, new storage is allocated for 'vla' at every iteration,
eventually exhausting all available auto storage.

Now, is this just implementation dependant and this kind of construct
should be avoided, or is one of these compilers not working correctly?

Should a bug report be filed?
I'd file it, yeah.

6.2.4#6:

"such an object" "does have"
For [an object with automatic storage duration] that [has] a variable
length array type, its lifetime extends from the declaration of the
object until execution of the program leaves the scope of the
declaration.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 6 '08 #3
Jack Klein wrote:
>
I'd complain if I used this feature of his compiler, although I have
plonked him and don't use his compiler at all anymore.

Consider a similar case:

#include <stdio.h>

void func(int x)
{
printf("%p\n", (void *)&x); // missing ")" fixed
}

int main(void)
{
int x = 0;
func();
func();
func();
return x;
}

I don't think I have ever used an implementation where the three calls
to func() would output different values.

Do you think the C standard requires it to be the same? If not, do
you think it should?
I am happy you do not use my compiler system since your
buggy code will not even compile:

Error tbb.c: 11 insufficient number of arguments to `func'
Error tbb.c: 12 insufficient number of arguments to `func'
Error tbb.c: 13 insufficient number of arguments to `func'
3 errors, 0 warnings

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Mar 6 '08 #4
jacob navia <ja***@nospam.orgwrites:
Erwin Lindemann wrote:
>If a VLA appears within a loop body, it seems the behavior is
different with two different compilers I tried. I looked at the
standard text, but couldn't find a definite answer there either.

There is no definite answer. It is implementation dependent.
>Consider the following test program

/* begin foo.c */
#include <stdio.h>
#include <string.h>

void test(int n, size_t size)
{
int i;

for(i = 0; i < n; i++) {
unsigned char vla[size]; //<<<<<<<<<<<<<<<<<
memset(vla, (i & 255), size);
printf("step %d: vla=%p\n", i, &vla[0]);
}
}

int main(void)
{
test(10, 256*1024L);
return 0;
}
/* end foo.c */

With gcc, 'vla' is reused in every iteration, i.e., the address
of 'vla[0]' is identical in every step.
The standard doesn't say that "vla" must have the same address at
every iteration of the loop, and it shouldn't matter whether it does
or not. In fact, a strictly conforming program can't tell whether the
same memory is re-used, since the address becomes invalid at the end
of the block, when the lifetime of "vla" has ended.

*However*, the lifetime of "vla" begins at its declaration and ends at
the end of the block (the loop body). There's a distinct array object
for each iteration of the loop, but the lifetimes of these objects do
not overlap. Since the program apparently dies with an out-of-memory
condition, it appears that the generated code is allocating space for
"vla" at the point of declaration *and not deallocating it* at the end
of the array's lifetime.

An argument could probably be made that this behavior doesn't violate
the standard, but it's certainly a bug. I don't care whether "vla"
has the same address each time; I care that the program crashes.

Consider:

for (i = 0; i < n; i ++) {
unsigned char arr[2000];
/* ... */
}

Would it be acceptable for n copies of "arr" to have memory allocated
for them simultaneously, causing the program to die? If not, why
would it be acceptable for a VLA?

Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?

[...]
>Should a bug report be filed?
IMHO, yes.
You can only file a bug report if you buy maintenance at premium rates.
I have a special price for clique members sorry!
*Yawn*.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 6 '08 #5
Erwin Lindemann <el******@wupp.invalidwrote:
#
# If a VLA appears within a loop body, it seems the behavior is
# different with two different compilers I tried. I looked at the
# standard text, but couldn't find a definite answer there either.

This is a 48 year old issue. Answer is both block and procedure
level allocation have their benefits so both will continue to be
used. Program to cope with either. In particular don't allocate
arrays in loops unless you're prepared to have the entire amount
allocated.

If you must allocate in a loop and you must have it released
at the end of the loop, put the loop body in a separate function.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
TEMPORARILY CLOSED
BE OPENED AFTER FIRST PERIOD
Mar 6 '08 #6
SM Ryan <wy*****@tango-sierra-oscar-foxtrot-tango.fake.orgwrites:
Erwin Lindemann <el******@wupp.invalidwrote:
#
# If a VLA appears within a loop body, it seems the behavior is
# different with two different compilers I tried. I looked at the
# standard text, but couldn't find a definite answer there either.

This is a 48 year old issue. Answer is both block and procedure
level allocation have their benefits so both will continue to be
used. Program to cope with either. In particular don't allocate
arrays in loops unless you're prepared to have the entire amount
allocated.
Regardless of whether block or procedure-level allocation is used,
though, there must always be exactly one instance of the object.

On (non-broken) implementations with block-level allocation, the
following:

void foo(int a)
{
for (i=0; i!=10000; ++i) {
int v;
/* do something with v; */
}
}

would not result in 10,000 "v" objects being simultaneously allocated;
neither should an "int v[a];" result in such (and the standard
requires that it does not).

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 6 '08 #7
Keith Thompson wrote:
Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?
I replied with a lengthy explanation that you apparently
did not bother to READ.

The program dies because for a VLA I do not make the
optimization that the variable "size" is a loop invariant,
i.e. does not change within the loop.

If you replace
int tab[size];

with

int tab[size*i+1];

gcc will ALSO produce different arrays for each iteration.
As I explained (and repeat here again) this is an optimization
that I do not do and gcc does.

Please read my posts before replying

thanks

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Mar 6 '08 #8
jacob navia <ja***@nospam.comwrites:
Keith Thompson wrote:
>Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?

I replied with a lengthy explanation that you apparently
did not bother to READ.
No, you didn't. You explained why new arrays are created, which is
fine.. You have failed to explain why the old ones aren't destroyed,
as they are required to have been.
The program dies because for a VLA I do not make the
optimization that the variable "size" is a loop invariant,
i.e. does not change within the loop.

If you replace
int tab[size];

with

int tab[size*i+1];

gcc will ALSO produce different arrays for each iteration.
Sure. Hopefully, though, it will also continue to destroy the old ones
first, just as it's required to.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 6 '08 #9
jacob navia wrote:
Keith Thompson wrote:
>Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?

I replied with a lengthy explanation that you apparently
did not bother to READ.

The program dies because for a VLA I do not make the
optimization that the variable "size" is a loop invariant,
i.e. does not change within the loop.
So you know exactly where the bug in your compiler is and how to fix it.
Good.
But why then don't you you say so explictly?
If you replace
int tab[size];

with

int tab[size*i+1];

gcc will ALSO produce different arrays for each iteration.
Irrelevant, as others pointed out
As I explained (and repeat here again) this is an optimization
that I do not do and gcc does.
And it doesn't die. This _is_ relevant.
Please read my posts before replying
Please be more clear in what you want to say.

Bye, Jojo
Mar 6 '08 #10
On Thu, 06 Mar 2008 20:02:22 +0100, jacob navia wrote:
If you replace
int tab[size];

with

int tab[size*i+1];

gcc will ALSO produce different arrays for each iteration.
If you print a pointer to the end of the array, you'll find it has the
same address every time. It happens to be a system with a stack that grows
downwards, so it's not practical to give the start of the array a fixed
location, but there's no reason why the end should not be given one.
Mar 6 '08 #11
Micah Cowan wrote:
jacob navia <ja***@nospam.comwrites:
>Keith Thompson wrote:
>>Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?
I replied with a lengthy explanation that you apparently
did not bother to READ.

No, you didn't. You explained why new arrays are created, which is
fine.. You have failed to explain why the old ones aren't destroyed,
as they are required to have been.
Required by whom?

you?

Thompson?

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Mar 6 '08 #12
jacob navia wrote:
Micah Cowan wrote:
>jacob navia <ja***@nospam.comwrites:
>>Keith Thompson wrote:
Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?

I replied with a lengthy explanation that you apparently
did not bother to READ.

No, you didn't. You explained why new arrays are created, which is
fine.. You have failed to explain why the old ones aren't destroyed,
as they are required to have been.

Required by whom?

you?

Thompson?
common sense?

Bye, Jojo
Mar 6 '08 #13
Joachim Schmitz wrote:
jacob navia wrote:
>Keith Thompson wrote:
>>Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?
I replied with a lengthy explanation that you apparently
did not bother to READ.

The program dies because for a VLA I do not make the
optimization that the variable "size" is a loop invariant,
i.e. does not change within the loop.
So you know exactly where the bug in your compiler is and how to fix it.
Good.
But why then don't you you say so explictly?
because there is no bug./

Nowhere in the standard it is written that I must free those
arrays
>If you replace
int tab[size];

with

int tab[size*i+1];

gcc will ALSO produce different arrays for each iteration.
Irrelevant, as others pointed out
>As I explained (and repeat here again) this is an optimization
that I do not do and gcc does.
And it doesn't die. This _is_ relevant.
not to me

The standard does not specify that those arrays should be destroyed.
They are no longer available, that's all.
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Mar 6 '08 #14
jacob navia wrote:
Joachim Schmitz wrote:
>jacob navia wrote:
>>Keith Thompson wrote:
Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?

I replied with a lengthy explanation that you apparently
did not bother to READ.

The program dies because for a VLA I do not make the
optimization that the variable "size" is a loop invariant,
i.e. does not change within the loop.
So you know exactly where the bug in your compiler is and how to fix
it. Good.
But why then don't you you say so explictly?

because there is no bug./
OK, see how unclear your wording was?
Nowhere in the standard it is written that I must free those
arrays
And what does common sense say? Isn't it you how constantly wants to improve
the standard?
>>If you replace
int tab[size];

with

int tab[size*i+1];

gcc will ALSO produce different arrays for each iteration.
Irrelevant, as others pointed out
>>As I explained (and repeat here again) this is an optimization
that I do not do and gcc does.
And it doesn't die. This _is_ relevant.

not to me

The standard does not specify that those arrays should be destroyed.
They are no longer available, that's all.
Even if it's not required by a standard, this is a Quality Of Implemenation
issue.
Destroying those arrays would surely not violate the standard, would it?
And I'd find such a "feature" much more usefull than a printf format
specified for complex numbers...

Bye, Jojo
Mar 6 '08 #15
"Joachim Schmitz" <no*********@schmitz-digital.dewrites:
jacob navia wrote:
>Micah Cowan wrote:
>>jacob navia <ja***@nospam.comwrites:

Keith Thompson wrote:
Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?
>
I replied with a lengthy explanation that you apparently
did not bother to READ.

No, you didn't. You explained why new arrays are created, which is
fine.. You have failed to explain why the old ones aren't destroyed,
as they are required to have been.

Required by whom?

you?

Thompson?

common sense?
In addition to the standard, the relevant text of which has been
quoted numerous times on this thread.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 6 '08 #16
Joachim Schmitz wrote:
Even if it's not required by a standard, this is a Quality Of Implemenation
issue.
Destroying those arrays would surely not violate the standard, would it?
And I'd find such a "feature" much more usefull than a printf format
specified for complex numbers...
Allocating a variable length array within a loop?
Look, I work for the regulars here, fixing things that are not broken
like this same person that insisted on calling a function
"abs" and complaining that stdlib.h defines "abs" and that he
receives an error message
The same guy that starts now this thread.

Yes, he can now BUY a maintenance contract and I
will do it after I receive his money ok?

The same people try to destroy lcc-win saying that is
commercial and that I am just here for the money I do.

OK

Then PAY!
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Mar 6 '08 #17
Micah Cowan wrote:
"Joachim Schmitz" <no*********@schmitz-digital.dewrites:
>jacob navia wrote:
>>Micah Cowan wrote:
jacob navia <ja***@nospam.comwrites:

Keith Thompson wrote:
>Or perhaps I've misunderstood what's going on here. I don't have
>lcc-win, so I can't test it myself. jacob, can you explain why
>the program dies?
>>
I replied with a lengthy explanation that you apparently
did not bother to READ.

No, you didn't. You explained why new arrays are created, which is
fine.. You have failed to explain why the old ones aren't
destroyed, as they are required to have been.
Required by whom?

you?

Thompson?

common sense?

In addition to the standard, the relevant text of which has been
quoted numerous times on this thread.
I found it only once, by you. And I'm not enough of a language lawyer to
determine whether that realy requires what you claim it does.
Jack Klein called it a QOI issue (and AFAIR he is a language lawyer), and I
agree that it is _at least_ that, a QOI issue.

Bye, Jojo
Mar 6 '08 #18
"Joachim Schmitz" <no*********@schmitz-digital.dewrites:
jacob navia wrote:
>Joachim Schmitz wrote:
>>jacob navia wrote:
The program dies because for a VLA I do not make the
optimization that the variable "size" is a loop invariant,
i.e. does not change within the loop.

So you know exactly where the bug in your compiler is and how to fix
it. Good.
But why then don't you you say so explictly?

because there is no bug./

OK, see how unclear your wording was?
Not unclear, just irrelevant. That he doesn't make some optimization is
no bug. The bug is that he leaks memory.
>Nowhere in the standard it is written that I must free those
arrays
You obviously haven't been reading. *Sigh* here it is again, (in a
previous version I even clarified some wording based on context, I
won't bother here since it's doubtful you'll read it this time
either):

6.2.4#6:
For such an object that does have a variable length array type, its
lifetime extends from the declaration of the object until execution of
the program leaves the scope of the declaration.

That scope is exited and re-entered upon every iteration (a compound
statement being just the single statement that is run by for).
And what does common sense say? Isn't it you how constantly wants to improve
the standard?
Agreed. Even if the standard "allowed" your behavior, it's clearly
brain-dead to leak memory wherever you feel like it.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 6 '08 #19
jacob wrote:
) If I change the marked line above to
)
) unsigned char vla[size*i+1];
)
) and change the size expression in the memset call to
) the same expression, gcc will produce the following
) output in my linux box:
) step 0: vla=0xbffff990
) step 1: vla=0xbffbf990
) step 2: vla=0xbff7f990
) step 3: vla=0xbff3f990
) step 4: vla=0xbfeff990
) step 5: vla=0xbfebf990
) step 6: vla=0xbfe7f990
) step 7: vla=0xbfe3f990
) step 8: vla=0xbfdff990
) step 9: vla=0xbfdbf990

Note that the difference between the addresses is the same each time, and
happens to be equal to 'size'. It is very probable that the *end* address
of the allocated block is the same each time. The stack probably grows
downward on this implementation.

The point is that the allocated blocks *overlap*.

) gcc is doing simply a constant propagation. It notices that the

No, gcc is destroying and reusing each block after its lifetime ends.
If the bock happens to be the same size, it happens to end up at the
same place by coincidence.

) expression in the VLA size is a constant expression within the
) affected block, and optimizes the case you presented above

No optimization is needed for this special case.

) to reuse always the same block. Fine, maybe I could do such an
) optimization too, so that the clique of comp.lang.c (where you
) belong) can have a harder time, but what for? This optimization
) would only optimize a special case.

As shown above, this is false. It works for *all* cases.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
Mar 6 '08 #20
jacob navia <ja***@nospam.comwrites:
because there is no bug./

Nowhere in the standard it is written that I must free those
arrays
IMHO, this point of view is as formalist as some about which you often
complain (again IMHO, sometimes rightfully, sometimes wrongly, but that's
another story).

Yours,

--
Jean-Marc
Mar 6 '08 #21
In article <fq**********@aioe.org>, jacob navia <ja***@nospam.orgwrote:
>Allocating a variable length array within a loop?
Why is that any more unreasonable than declaring a normal array in a loop?

-- Richard

--
:wq
Mar 6 '08 #22
On Thu, 06 Mar 2008 10:12:39 -0800, Keith Thompson <ks***@mib.org>
wrote in comp.lang.c:
jacob navia <ja***@nospam.orgwrites:
Erwin Lindemann wrote:
If a VLA appears within a loop body, it seems the behavior is
different with two different compilers I tried. I looked at the
standard text, but couldn't find a definite answer there either.
There is no definite answer. It is implementation dependent.
Consider the following test program

/* begin foo.c */
#include <stdio.h>
#include <string.h>

void test(int n, size_t size)
{
int i;

for(i = 0; i < n; i++) {
unsigned char vla[size]; //<<<<<<<<<<<<<<<<<
memset(vla, (i & 255), size);
printf("step %d: vla=%p\n", i, &vla[0]);
}
}

int main(void)
{
test(10, 256*1024L);
return 0;
}
/* end foo.c */

With gcc, 'vla' is reused in every iteration, i.e., the address
of 'vla[0]' is identical in every step.

The standard doesn't say that "vla" must have the same address at
every iteration of the loop, and it shouldn't matter whether it does
or not. In fact, a strictly conforming program can't tell whether the
same memory is re-used, since the address becomes invalid at the end
of the block, when the lifetime of "vla" has ended.
Really? I see nothing that makes the OP's program, which you quoted
in full above, not strictly conforming. And the output of that
program most certainly does generate output that shows the same memory
is reused by one implementation, not by another.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Mar 7 '08 #23
Erwin Lindemann wrote:
If a VLA appears within a loop body, it seems the behavior is
different with two different compilers I tried. I looked at the
standard text, but couldn't find a definite answer there either.

Consider the following test program

/* begin foo.c */
#include <stdio.h>
#include <string.h>

void test(int n, size_t size)
{
int i;

for(i = 0; i < n; i++) {
unsigned char vla[size];
memset(vla, (i & 255), size);
printf("step %d: vla=%p\n", i, &vla[0]);
}
}

int main(void)
{
test(10, 256*1024L);
return 0;
}
/* end foo.c */

With gcc, 'vla' is reused in every iteration, i.e., the address
of 'vla[0]' is identical in every step.

However, with lcc-win32, output is as follows...

step 0: vla=0x002ffea0
step 1: vla=0x002bfea0
step 2: vla=0x0027fea0
step 3: vla=0x0023fea0
[*CRASH*]

, meaning, new storage is allocated for 'vla' at every iteration,
eventually exhausting all available auto storage.

Now, is this just implementation dependant and this kind of construct
should be avoided, or is one of these compilers not working correctly?

Should a bug report be filed?

Thanks
For one, &vla[0] == vla.

The array vla[] should be allocated on the stack, and popped off of it
at the end of the for loop, so indeed if the error is that you have run
out of memory, this is a pretty bad compiler error, I'd say.

It might not be a bad idea to allocate that memory on the heap using
malloc() (or alloca() if your compiler supports it). This way, you will
be able to use its return value to detect this and exit gracefully.

--
--Falcon Kirtaran
Mar 7 '08 #24
On Mar 6, 9:07 pm, Jack Klein <jackkl...@spamcop.netwrote:
On Thu, 06 Mar 2008 10:12:39 -0800, Keith Thompson <ks...@mib.org>
wrote in comp.lang.c:
jacob navia <ja...@nospam.orgwrites:
Erwin Lindemann wrote:
>If a VLA appears within a loop body, it seems the behavior is
>different with two different compilers I tried. I looked at the
>standard text, but couldn't find a definite answer there either.
There is no definite answer. It is implementation dependent.
>Consider the following test program
>/* begin foo.c */
>#include <stdio.h>
>#include <string.h>
>void test(int n, size_t size)
>{
> int i;
> for(i = 0; i < n; i++) {
> unsigned char vla[size]; //<<<<<<<<<<<<<<<<<
> memset(vla, (i & 255), size);
> printf("step %d: vla=%p\n", i, &vla[0]);
> }
>}
>int main(void)
>{
> test(10, 256*1024L);
> return 0;
>}
>/* end foo.c */
>With gcc, 'vla' is reused in every iteration, i.e., the address
>of 'vla[0]' is identical in every step.
The standard doesn't say that "vla" must have the same address at
every iteration of the loop, and it shouldn't matter whether it does
or not. In fact, a strictly conforming program can't tell whether the
same memory is re-used, since the address becomes invalid at the end
of the block, when the lifetime of "vla" has ended.

Really? I see nothing that makes the OP's program, which you quoted
in full above, not strictly conforming.
It prints pointers, in implementation-defined format.
And the output of that
program most certainly does generate output that shows the same memory
is reused by one implementation, not by another.
It shows that implementation prints different hex
strings for those arrays, not that memory is reused
or not reused. *We know* what in that particular
setup those hex strings mean, but it's not something
a strictly conforming program could use to judge about
memory blocks (and that doesn't even make sense
from the standard point of view, a dead object is
not an object). What does show non-conformance is
the crash.

Yevgen
Mar 7 '08 #25
On Mar 5, 5:38*pm, Erwin Lindemann <elind...@wupp.invalidwrote:
However, with lcc-win32, output is as follows...

step 0: vla=0x002ffea0
step 1: vla=0x002bfea0
step 2: vla=0x0027fea0
step 3: vla=0x0023fea0
[*CRASH*]
See, this is what happens when the compiler writer becomes infatuated
with alloca. :)
Mar 7 '08 #26
On Mar 6, 11:02*am, jacob navia <ja...@nospam.comwrote:
Keith Thompson wrote:
Or perhaps I've misunderstood what's going on here. *I don't have
lcc-win, so I can't test it myself. *jacob, can you explain why the
program dies?

I replied with a lengthy explanation that you apparently
did not bother to READ.

The program dies because for a VLA I do not make the
The program dies because you aren't cleaning up the memory when a
block terminates.
optimization that the variable "size" is a loop invariant,
i.e. does not change within the loop.

If you replace
* * * * int tab[size];

with

* * * * int tab[size*i+1];
This tab could still be allocated in the same space. If the stack
grows downward, the starting address will be different. However, I
would expect the end address to be the same. Or very close---alignment
may cause it to jitter slightly.
gcc will ALSO produce different arrays for each iteration.
Oh really?

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

void test(int n, size_t size)
{
int i;

for(i = 0; i < n; i++) {
unsigned char vla[size+256*i];
memset(vla, (i & 255), size);
printf("step %d: vla address range == [%p,%p)\n", i,
(void *) vla, (void *) vla + size + 256 * i);
}
}
int main(void)
{
test(10, 256*1024L);
return 0;
}
step 0: vla address range == [0xbffbf990,0xbffff990)
step 1: vla address range == [0xbffbf890,0xbffff990)
step 2: vla address range == [0xbffbf790,0xbffff990)
step 3: vla address range == [0xbffbf690,0xbffff990)
step 4: vla address range == [0xbffbf590,0xbffff990)
step 5: vla address range == [0xbffbf490,0xbffff990)
step 6: vla address range == [0xbffbf390,0xbffff990)
step 7: vla address range == [0xbffbf290,0xbffff990)
step 8: vla address range == [0xbffbf190,0xbffff990)
step 9: vla address range == [0xbffbf090,0xbffff990)

Different starting address, same end. Obviously, someting like alloca
is going on, except that the allocation is tied to the block, not to
the function.
As I explained (and repeat here again) this is an optimization
that I do not do and gcc does.
Bahahahaha. I don't think what gcc is doing is called optimization.
It's called getting the semantics right. That's what gcc is doing (and
not you).
Mar 7 '08 #27
On Mar 6, 11:41*am, jacob navia <ja...@nospam.comwrote:
Nowhere in the standard it is written that I must free those
arrays

The standard does not specify that those arrays should be destroyed.
They are no longer available, that's all.
Sure, the standard doesn't explicitly say anywhere that the generated
code must not introduce software defects which are not present in the
source code, such as memory leaks. So you're off the hook?

Why not also generate code that randomly freezes? The standard doesn't
specify maximum time which must elapse from the evaluation of one
expression to the next.

Boy, how quick are we to retreat to the standard. Did you know that it
doesn't even say there /is/ such thing as a stack? And here you are,
asking my compiler to clean up something that doesn't even exist!
Mar 7 '08 #28
jacob navia <ja***@nospam.comwrites:
Keith Thompson wrote:
>Or perhaps I've misunderstood what's going on here. I don't have
lcc-win, so I can't test it myself. jacob, can you explain why the
program dies?

I replied with a lengthy explanation that you apparently
did not bother to READ.
I did.
The program dies because for a VLA I do not make the
optimization that the variable "size" is a loop invariant,
i.e. does not change within the loop.
That optimization, or the lack of it, is not the problem. In cases
where the size of the VLA is *not* a loop invariant, code generated by
gcc will work correctly, and code generated by lcc-win apparently will
blow up.
If you replace
int tab[size];

with

int tab[size*i+1];

gcc will ALSO produce different arrays for each iteration.
It doesn't matter that they're different arrays. What matters is that
only one exists at a time.

Consider this:
for (i = 0; i < 1000; i ++) {
int obj;
}
Would it be reasonable for space to be allocated for 1000 instances of
"obj" simultaneously, before any of them have been deallocated?

Consider this:
for (i = 0; i < 1000; i ++) {
int arr[1000];
}
Would it be reasonable for space to be allocated for 1000 instances of
"arr" simultaneously, before any of them have been deallocated?

Consider this:
for (i = 0; i < 1000; i ++) {
int vla[rand() % 1000];
}
Would it be reasonable for space to be allocated for 1000 instances of
"vla" simultaneously, before any of them have been deallocated?

Why in the world would you answer those three questions differently?

And can you *please* try to respond without sarcasm?

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 7 '08 #29
Kaz Kylheku wrote:
On Mar 5, 5:38 pm, Erwin Lindemann <elind...@wupp.invalidwrote:
>However, with lcc-win32, output is as follows...

step 0: vla=0x002ffea0
step 1: vla=0x002bfea0
step 2: vla=0x0027fea0
step 3: vla=0x0023fea0
[*CRASH*]

See, this is what happens when the compiler writer becomes infatuated
with alloca. :)
There are two kinds of people in this world.

The people that work, create things, offer them to the others.

The people that do not move a single finger, and limit themselves
to criticizing the first ones.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Mar 7 '08 #30
jacob navia wrote:
There are two kinds of people in this world.
Absolutely. Those who think as I do, and the others. :-)
The people that work, create things, offer them to the others.

The people that do not move a single finger, and limit themselves
to criticizing the first ones.
Hmm. Methinks these two groups are one - the two sides of a
single coin, so to speak. (Let's not allow ourselves to become
/too/ self-righteous.)

Kaz has offered some pretty nifty stuff here. I have some it
carefully tucked away just because it struck me as both unobvious
and elegant.

It's worth noting that the coin not only has two sides - it also
has an edge, which probably makes room for those who teach and
share their understanding with those who lack it...

....but it's still one coin.

TGIF :-)

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto
Mar 7 '08 #31
On 7 Mar 2008 at 9:17, jacob navia wrote:
Kaz Kylheku wrote:
>On Mar 5, 5:38 pm, Erwin Lindemann <elind...@wupp.invalidwrote:
>>However, with lcc-win32, output is as follows...

step 0: vla=0x002ffea0
step 1: vla=0x002bfea0
step 2: vla=0x0027fea0
step 3: vla=0x0023fea0
[*CRASH*]

See, this is what happens when the compiler writer becomes infatuated
with alloca. :)

There are two kinds of people in this world.

The people that work, create things, offer them to the others.

The people that do not move a single finger, and limit themselves
to criticizing the first ones.
We certainly see that clearly in clc - the Clique have nothing better to
do with their time than tut-tut and complain about top-posting or
voiding main, to provide some variety in amongst their constant savaging
of Jacob.

Mar 7 '08 #32
In article <87************@news.bourguet.org>,
Jean-Marc Bourguet <jm@bourguet.orgwrote:
>jacob navia <ja***@nospam.comwrites:
>because there is no bug./

Nowhere in the standard it is written that I must free those
arrays

IMHO, this point of view is as formalist as some about which you often
complain (again IMHO, sometimes rightfully, sometimes wrongly, but that's
another story).

Yours,

--
Jean-Marc
What Jacob is demonstrating (albeit subtly) is how the Clique members
act as if the standard is absolute truth (cannot be questioned and does not
need to be defended) - right up until it suits their purposes to do otherwise.

Much as religious fundy leaders do, in re: the Bible.

As I've pointed out several times previously, CLC very much resembles
fundy religion - and the temperments of the folks here closely resembles
that of Bush voters.

Mar 7 '08 #33
In article <9a**********************************@i7g2000prf.g ooglegroups.com>,
Kaz Kylheku <kk******@gmail.comwrote:
>On Mar 6, 11:41*am, jacob navia <ja...@nospam.comwrote:
>Nowhere in the standard it is written that I must free those
arrays

The standard does not specify that those arrays should be destroyed.
They are no longer available, that's all.

Sure, the standard doesn't explicitly say anywhere that the generated
code must not introduce software defects which are not present in the
source code, such as memory leaks. So you're off the hook?
What Jacob is demonstrating (albeit subtly) is how the Clique members
act as if the standard is absolute truth (cannot be questioned and does
not need to be defended) - right up until it suits their purposes to do
otherwise.

Much as religious fundy leaders do, in re: the Bible.

As I've pointed out several times previously, CLC very much resembles
fundy religion - and the temperments of the folks here closely resembles
that of Bush voters.
>Why not also generate code that randomly freezes? The standard doesn't
specify maximum time which must elapse from the evaluation of one
expression to the next.
Exactly so. Well done.
>Boy, how quick are we to retreat to the standard. Did you know that it
doesn't even say there /is/ such thing as a stack? And here you are,
asking my compiler to clean up something that doesn't even exist!
Yes. The standard is absolutely true and valid, in all its particulars.
See above.

Mar 7 '08 #34
# Regardless of whether block or procedure-level allocation is used,
# though, there must always be exactly one instance of the object.

This issue has been around since Algol 60. You can learn to
cope with the procedure level allocation or you can watch your
programs break.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
If your job was as meaningless as theirs, wouldn't you go crazy too?
Mar 7 '08 #35
On Mar 7, 1:17*am, jacob navia <ja...@nospam.comwrote:
Kaz Kylheku wrote:
On Mar 5, 5:38 pm, Erwin Lindemann <elind...@wupp.invalidwrote:
However, with lcc-win32, output is as follows...
step 0: vla=0x002ffea0
step 1: vla=0x002bfea0
step 2: vla=0x0027fea0
step 3: vla=0x0023fea0
[*CRASH*]
See, this is what happens when the compiler writer becomes infatuated
with alloca. :)

There are two kinds of people in this world.
Yes, indeed: those who dichotomize everything, those who think, and
those who cannot count.
The people that do not move a single finger, and limit themselves
to criticizing the first ones.
Like those goddamned software testers that keep making work for us!
Mar 7 '08 #36
jacob navia wrote:
Look, I work for the regulars here, fixing things that are not broken
like this same person that insisted on calling a function
"abs" and complaining that stdlib.h defines "abs" and that he
receives an error message
The same guy that starts now this thread.
What are you talking about? I never claimed such a thing. Furthermore,
according to ISO/IEC 9899:1999, 7.20.6.1, <stdlib.his *required* to
declare 'abs()' (well, declare, not define; sloppy wording on your part?)

Perhaps you are confusing me with somebody else?
Thanks
--
Erwin Lindemann

Mar 8 '08 #37
jacob navia <ja***@nospam.comwrites:
[...]
Allocating a variable length array within a loop?
Look, I work for the regulars here, fixing things that are not broken
like this same person that insisted on calling a function
"abs" and complaining that stdlib.h defines "abs" and that he
receives an error message
[...]

It wasn't "abs" (which must be defined in <stdlib.h>). lcc-win's
stdlib.h defined "min" and "max" macros in <stdlib.h>, in violation of
the standard. See the "min/max in stdlib.h?!" thread from January,
starting with
<http://groups.google.com/group/comp.lang.c/msg/26e05e43e19aac05>.

You responded at the time that they would go away in conforming mode
in the next release.

I congratulate you on your speed in correcting errors that are
reported here. But since I personally care more about this newsgroup
than about your compiler (nothing personal, I'm just not a Windows
programmer), I'd be happier without the drama that ensues between the
bug report and the fix.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 8 '08 #38

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

Similar topics

16
by: steflhermitte | last post by:
Dear cpp-ians, I am working with a structure: struct meta_segment { long double id; long double num; long double mean; bool done;
10
by: yawnmoth | last post by:
i've written some javascript code that i believe should set a form variable to a certain value, depending on what the user clicks on. unfortunately, it isn't working. here's the url: ...
27
by: Mike P | last post by:
I will be passing my function a two dimensional array of varying length. Within that array is one data point, and the number of times it should loop through. So, for example, I might pass this...
5
by: dam_fool_2003 | last post by:
Hai, I studied that the array size is fixed. But I come across a word called "variable length array". Is it possible to change the array size? So I tried the following: #include<stdio.h>...
6
by: Carl-Olof Almbladh | last post by:
Already in the 1st edition of the "White book", Kerigham and Ritchie states the "C is a general purpose language". However, without what is usually called "assumed size arrays" and built-in...
6
by: JNY | last post by:
Hello, Is it possible to declare an array with variable indeces? i.e. int x = 4; int myArray; for (j = 0;j < 5;j++) {
23
by: Russ Chinoy | last post by:
Hi, This may be a totally newbie question, but I'm stumped. If I have a function such as: function DoSomething(strVarName) { ..... }
6
by: mechanicfem | last post by:
In f(), I am passing a parameter of array type - /size/ indicates the array's length: void f(char arr, int size); In the c99 stds, it mentions the use of and says (I think) that it can be...
3
by: jaime | last post by:
Hi all. The source code download bundle for "Beginning C: From Novice to Professional, Fourth Edition" (ISBN: 1590597354) (Horton/Apress) contains a C source file (program9_09.c) which contains...
7
by: Cromulent | last post by:
In section 6.7.5.2 it states the following: If the size is not present, the array type is an incomplete type. If the size is*instead of being an expression, the array type is a variable length...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
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
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
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...

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.