views:

72

answers:

2

I have the following program test.cc:

#include <iostream>
unsigned char bogus1[] = {
  // Changing # of periods (0x2e) changes output after periods.
  0x2e, 0x2e, 0x2e, 0x2e
};
unsigned int bogus2 = 1816; // Changing this value changes output.

int main()
{
  std::clog << bogus1;
}

I build it with:

g++ -g -c -o test.o test.cc; g++ -static-libgcc -o test test.o

Using g++ version 3.4.6

I run it through valgrind and nothing is reported wrong.

However the output has two extra control characters and looks like this:

....

Thats a control-X and a control-G at the end.

If you change the value of bogus2 you get different control characters. If you change the number of periods in the array the issue goes away or changes.

I suspect it is a memory corruption bug in the compiler or iostream package.

What is going on here?

+7  A: 

You're missing the '\0' at the end of the string

unsigned char bogus1[] = {
  0x2e, 0x2e, 0x2e, 0x2e, 0x00
};
BlueRaja - Danny Pflughoeft
Then why doesn't valgrind report ABR?
WilliamKF
+8  A: 

In C/C++, a string is usually stored as a null-terminated char array.

Your unsigned char array isn't null-terminated. Usually it would look something like this:

unsigned char bogus1[] = {
  0x2e, 0x2e, 0x2e, 0x2e,
  0x00 // terminating NUL byte
};

If it isn't null-terminated, output will continue until a NUL byte is found, that's why it outputs values that are placed in the memory behind your array, like the int bogus2 (which is 0x00000718 in hex, stored in little endian format => 0x18 = Ctrl-X, 0x07 = Ctrl-G, 0x00 ends the output)

schnaader
Then why doesn't valgrind report ABR?
WilliamKF
I don't think valgrind can/should report anything here. bogus2 is memory occupied by you and it even has a NUL byte in it (the int is 0x00000718), so there's no access to memory not used by your program.
schnaader
Also note that you're passing bogus1[0] to std:clog, not bogus1[100] or something like this, so you're passing a valid pointer inside of your array. std:clog uses this as a pointer and increases it so that it goes beyong your array's bounds, but I think this is out of valgrind's scope.
schnaader
So why isn't the std::clog operator<<() able to find the size of the array and not go past the end?
WilliamKF
@WilliamKF: "Size of an array" is a bit of a misnomer in C++. All << sees is a memory address - it reads until it hits a '\0'
BlueRaja - Danny Pflughoeft
@WilliamKF: C++ does not do bounds checking automatically. You have to do it yourself. For C-style string operations (such as working with a char array) this bounds checking is done by chugging through memory, until the algorithm hits a NULL. Arrays don't automatically have a bound built-in, and your algorithm has to manually do this bounds checking.
Merlyn Morgan-Graham