#include <iostream>
using namespace std;
int main() {
int rows = 10;
int cols = 9;
int opt[rows][cols] = {0};
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
std::cout << opt[i][j] << " ";
}
std::cout << "\n";
}
return 0;
}
Output:
0 32767 1887606704 10943 232234400 32767 1874154647 10943 -1
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
I'm using gcc 6.3, in https://www.codechef.com/ide
I'm expecting the first row to be all zeros. Shouldn't that be the case?
EDIT: I tested with const variables for rows and cols, and then it initialized to all zeroes. I feel this should throw a compile error instead of exhibiting this incorrect (and potentially dangerous) behavior.
If we look at the gcc 4.9 release notes it looks like they added support for initializating VLA with the expectation VLA would be supported in a future version of C++:
G++ supports C++1y variable length arrays. G++ has supported GNU/C99-style VLAs for a long time, but now additionally supports initializers and lambda capture by reference. In C++1y mode G++ will complain about VLA uses that are not permitted by the draft standard, such as forming a pointer to VLA type or applying sizeof to a VLA variable. Note that it now appears that VLAs will not be part of C++14, but will be part of a separate document and then perhaps C++17.
We can see it live that before 4.9 complains we can't initialize a VLA
error: variable-sized object 'opt' may not be initialized
int opt[rows][cols] = {0};
^
but in 4.9.1 and after it stops complaining and it does not have the same bug we see in more recent versions.
So it looks like a regression.
Note that clang refuses to allow initialization of a VLA (which they support as an extension) see a live example. Which make sense since C99 does not allow initialization of VLA:
The type of the entity to be initialized shall be an array of unknown size or an object type that is not a variable length array type.
gcc bug report :SEGV on a VLA with excess initializer elements has a comment that provides some background on this feature:
(In reply to Jakub Jelinek from comment #16)
The bug here is in G++ accepting a VLA initializer with more elements than there is room for in the VLA, and then trashing the stack at runtime with the extra elements. It is a regression with respect to GCC 4.9.3 which implements C++ VLAs as specified in n3639 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3639.html). This is documented in GCC 4.9 changes (https://gcc.gnu.org/gcc-4.9/changes.html) which highlights the feature using the following example:
void f(int n) { int a[n] = { 1, 2, 3 }; // throws std::bad_array_length if n < 3 ...
VLAs were subsequently removed from C++, and also partially (but not completely) removed from G++, which causes C++ programs developed and tested with G++ 4.9 to break when ported to a later version.
C++ VLAs will be safer to use with the patch referenced in comment #9. It patch had to be reverted from GCC 6.0 because it caused problems in Java. Java has been removed and I plan/hope to resubmit the patch for GCC 8. (I wanted to do it for GCC 7 but didn't get to it.)