G++ Variable Size Array No Warning

g++ variable size array no warning?

ISO C++ disallows the use of variable length arrays, which g++ happily tells you if you increase the strictness of it by passing it the -pedantic flag.

Using -pedantic will issue a warning about things breaking the standard. If you want g++ to issue an error and with this refuse compilation because of such things; use -pedantic-errors.


g++ -Wall -pedantic -std=c++11 apa.cpp


apa.cpp: In function ‘int main(int, char**)’:
apa.cpp:8:13: warning: ISO C++ forbids variable length array ‘ints’ [-Wvla]
int ints[a];
^
apa.cpp:8:7: warning: unused variable ‘ints’ [-Wunused-variable]
int ints[a];
^

Warning ISO C++ forbids variable-size array with constant size array

The definition is required and searched for, at link-time. So yes, the size is unknown during the compilation phase.

You're write this:

class Constants
{
public:
static const unsigned int C_BufferSize = 128; //initialize here
};

And then only provide the definition in .cpp file:

const unsigned int Constants::C_BufferSize; //no initialization here

But then it makes better sense to make Constants a namespace instead of a class:

namespace Constants  //NOTE : a namespace now
{
static const unsigned int BufferSize = 128;
};

Seems more natural to me.

Variable sized array on the stack

They aren't allowed in standard C++, but they are allowed in standard C, and g++ allows them in C++ as well, as a language extension.

How then are variable sized arrays on the stack implemented?

See this question. The gist is that the size (n) gets evaluated and stored in a compiler-generated local variable, and then that much stack space is allocated. There's no law of physics that says the size of a stack variable has to be known at compile-time - it's merely simpler that way.

Why are they even necessary?

They aren't. As you aid, you can do the same thing with dynamic allocation.

Why can't we just use the heap for variable sized buffers?

Stack allocation is more efficient.

Compiler bug? g++ allows variable-size static arrays, unless function is templated

After compiling your code with -ansi on gcc 4.7.0, I was able to reproduce this warning:

warning: ISO C++ forbids variable length array 'bitVec' [-Wvla]

This warning appeared for both bitVec, not just the one in the template function. I then realized that the line nbits = 1e7; is assigning a double to an unsigned int. I think because of this, for some reason causes nbits to not be a constant expression. The reason your code is compiling for the non-templated version is because of the variable length array extension for gcc. Also, your version of gcc for some reason doesn't allow variable length arrays in function templates. To fix your code change 1e7; to 10000000.

EDIT

I asked another question concerning the rule. The answer is in C++03 the code is invalid, but in C++11 it is okay.

ISO C++ forbids variable-size array (compilation error)

200: vector *v[n]; can be fixed by initializing the vector:

vector* v = new vector[n];

207: float nfloat[numsvector]; can be fixed by dynamically allocating the array:

float* nfloat = new float[numsvector]

I believe these are the corresponding C memory allocations:

vector* v = malloc(n * sizeof(vector));

float* nfloat = malloc(numsvector * sizeof(float));

Why aren't variable-length arrays part of the C++ standard?

There recently was a discussion about this kicked off in usenet: Why no VLAs in C++0x.

I agree with those people that seem to agree that having to create a potential large array on the stack, which usually has only little space available, isn't good. The argument is, if you know the size beforehand, you can use a static array. And if you don't know the size beforehand, you will write unsafe code.

C99 VLAs could provide a small benefit of being able to create small arrays without wasting space or calling constructors for unused elements, but they will introduce rather large changes to the type system (you need to be able to specify types depending on runtime values - this does not yet exist in current C++, except for new operator type-specifiers, but they are treated specially, so that the runtime-ness doesn't escape the scope of the new operator).

You can use std::vector, but it is not quite the same, as it uses dynamic memory, and making it use one's own stack-allocator isn't exactly easy (alignment is an issue, too). It also doesn't solve the same problem, because a vector is a resizable container, whereas VLAs are fixed-size. The C++ Dynamic Array proposal is intended to introduce a library based solution, as alternative to a language based VLA. However, it's not going to be part of C++0x, as far as I know.

C compile error: Variable-sized object may not be initialized

I am assuming that you are using a C99 compiler (with support for dynamically sized arrays). The problem in your code is that at the time when the compilers sees your variable declaration it cannot know how many elements there are in the array (I am also assuming here, from the compiler error that length is not a compile time constant).

You must manually initialize that array:

int boardAux[length][length];
memset( boardAux, 0, length*length*sizeof(int) );

How do compilers treat variable length arrays

In the C99 version of the C standard, variable length arrays are permitted. However, they are not permitted in any version of C++; you're seeing a G++ extension. Note that Microsoft's C compiler does not fully support C99; since G++ supports C99 it's easy enough to apply the VLA support to C++ as an extension.

As to how the compiler usually implements VLAs, it's the same as alloca() (except that it has to keep the size around for sizeof) - the compiler saves the original stack pointer, then adjusts it down by however many bytes it calculates that it needs. The downside is function entry and exit is a bit more complicated as the compiler needs to store where to reset the stack pointer to rather than just adjusting by fixed constants.

GCC - no warning about an uninitialized array with -O0

This is a long-standing, documented limitation in GCC. Quoting the manual for GCC 3.0:

-Wuninitialized

Warn if an automatic variable is used without first being initialized or if a variable may be clobbered by a setjmp call.

These warnings are possible only in optimizing compilation, because they require data flow information that is computed only when optimizing. If you don't specify -O, you simply won't get these warnings.

The current version of the manual has actually removed the second paragraph of this quotation, saying instead "Because these warnings depend on optimization, the exact variables or elements for which there are warnings depends on the precise optimization options and version of GCC used." This is because, at some point between GCC 3.0 (released 2001) and GCC 8.2 (released 2018) the compiler was improved so that it will give warnings for at least some uses of uninitialized variables when not optimizing. For instance, the trivial test

int foo(void) { int x; return x; }

does provoke a warning when compiled with GCC 8.2 using -O0 -Wall.

It is worth pointing out that perfect diagnosis of uninitialized variables reduces to the infamous Halting Problem—which means it can't be done. You can implement a set of rules that are conservatively correct (they will detect all uses of uninitialized variables, but they may claim that some variables are used uninitialized when they aren't), e.g. Java's definite assignment rules, but that approach has historically been unpopular among C programmers. Given a demand for minimal false positives but also quick compilation when not optimizing, GCC's approach of doing more elaborate analysis when optimization is on is understandable.



Related Topics



Leave a reply



Submit