Jump to content


[MSVC 6.0] Illegal compiler operation...?


5 replies to this topic

#1 Hyper

    Valued Member

  • Members
  • PipPipPip
  • 195 posts

Posted 23 November 2010 - 10:45 PM

Hello, and I'm just playing around with MSVC 6.0's compiler.

This statement is illegal:
char buffer[];

error C2133: 'buffer' : unknown size

That's a pretty convincing argument for me; How can you define an array without a known size?

This is what gets me: This is a legal statement:
char buffer[] = {0};

When ran in the debugger, it runs fine, and it has allocated 7 bytes for itself.
As you tell it to modify values, it allocates itself? 3 bytes (EG: buffer[8] = 'a';).

These both return a "size of 1":
sizeof(buffer);

(sizeof(buffer) / sizeof(buffer[0]))

However, the strlen() reflects what you'd expect sizeof operator to do!
Initially, strlen() returns 7 (why 7...?), then if you exceed 7, it becomes 11!

If anybody could provide an explanation, it'd be appreciated!
As far as I know, this is considered 'undefined behavior,' in the C/C++ language.

This is the program I am compiling, if anybody would like to try it.
#include <windows.h>

#include <iostream> // For sprintf()

using namespace std;


int main() {


    char buffer[] = {0};    // How is this a legal declaration?!

    char message[50] = {0}; // For sprintf'ing the data out


    // Insert 8 values (all 0x65)

    for (unsigned char x = 0; x < 8; x++) {

        buffer[x] = 'A';

    }


    // Returns a size of "1" and a strlen of "11" for me (MSVC 6.0)

    sprintf(message, "SIZE OF: %d\nSTRLEN: %d", (sizeof(buffer) / sizeof(buffer[0])), strlen(buffer));

    MessageBox(NULL, message, "", MB_OK);


    return 0;

}

“You may be disappointed if you fail, but you are doomed if you don't try.”
Beverly Sills

#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 5307 posts
  • LocationBellevue, WA

Posted 23 November 2010 - 11:24 PM

Writing beyond the end of the array certainly is in undefined-behavior territory, and I suspect you're only getting reasonable results because the compiler happened to have a few zero bytes here and there in the memory area after the array. I.e. the array has only one byte allocated, which is initialized with zero, and as soon as you overwrite that, strlen will run until it finds the next zero byte, wherever that happens to be (apparently one 7 bytes later, and another 11 bytes later). When you write the 'A' characters you are overwriting memory that could potentially be storing something else important, such as another variable, or even some executable code.

As for the syntax: buffer[] is allowed because you're giving, in the same line, an initialization value which shows how much space to allocate, i.e. 1 character. If you wrote 'char buffer[] = { 0, 1, 2, 3 };' then it would allocate 4 bytes. It's just a convenience thing. I believe you can also do something like 'char buffer[] = "Hello, world!";' which will automatically allocate enough space for the string (and null terminator) and fill in the appropriate values.
reedbeta.com - developer blog, OpenGL demos, and other projects

#3 Hyper

    Valued Member

  • Members
  • PipPipPip
  • 195 posts

Posted 24 November 2010 - 06:10 AM

Reedbeta said:

Writing beyond the end of the array certainly is in undefined-behavior territory, and I suspect you're only getting reasonable results because the compiler happened to have a few zero bytes here and there in the memory area after the array. I.e. the array has only one byte allocated, which is initialized with zero, and as soon as you overwrite that, strlen will run until it finds the next zero byte, wherever that happens to be (apparently one 7 bytes later, and another 11 bytes later). When you write the 'A' characters you are overwriting memory that could potentially be storing something else important, such as another variable, or even some executable code.

As for the syntax: buffer[] is allowed because you're giving, in the same line, an initialization value which shows how much space to allocate, i.e. 1 character. If you wrote 'char buffer[] = { 0, 1, 2, 3 };' then it would allocate 4 bytes. It's just a convenience thing. I believe you can also do something like 'char buffer[] = "Hello, world!";' which will automatically allocate enough space for the string (and null terminator) and fill in the appropriate values.
Ahh, okay. That's what about what I was thinking, but I wasn't sure if I was correct or not. :p

Yes, I'm aware of the latter (char buffer[] = { "Hello World!" }) and the like.
That's what made me a little curious as to how this was even allowed to compile.

Thanks, Reedbeta! :)
“You may be disappointed if you fail, but you are doomed if you don't try.”
Beverly Sills

#4 Nick

    Senior Member

  • Members
  • PipPipPipPip
  • 1227 posts
  • LocationOttawa, Ontario, Canada

Posted 24 November 2010 - 10:42 AM

This isn't Visual C++ 6.0 specific. It's just standard C++ semantics.

That said, you really may want to upgrade to Visual Studio 2010 Express. It's free, much more standards compliant, creates faster code, has a great IDE, etc.

#5 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 24 November 2010 - 02:57 PM

Hyper said:

This is what gets me: This is a legal statement:
char buffer[] = {0};

When ran in the debugger, it runs fine, and it has allocated 7 bytes for itself.
No, just 1.

Quote

As you tell it to modify values, it allocates itself? 3 bytes (EG: buffer[8] = 'a';).
Nope, your simply writing beyond the length of the buffer

Quote

However, the strlen() reflects what you'd expect sizeof operator to do!
Most certainly not! strlen() counts the number of characters until it finds a 0. If the buffer does not contain a 0, strlen will simply keep on counting. Also, if a buffer contains a 0 somewhere in the middle, strlen will stop before the end of the buffer. So, sizeof gives you the full size of the buffer known at compile time, while strlen() calculates the length of a zero terminated string at runtime. And even for constant strings, sizeof("Hello") is 6, while strlen("Hello") is 5.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#6 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 939 posts

Posted 24 November 2010 - 03:31 PM

The line 'buffer[x] = 'A';' actually produces a warning in VS10:
'warning C4789: destination of memory copy is too small'
"Stupid bug! You go squish now!!" - Homer Simpson





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users