views:

112

answers:

5

Hi, everyone

Please take a look at this piece of code. I'm allocating one byte for the first variable and another byte for the second one. However, it seems like the compiler allocates more (or I'm missing something). The program outputs both strings, even though their length is more the one byte.

void main() {
    char* some1 = malloc(1);
    sprintf(some1,"cool");
    char* some2 = malloc(1);
    sprintf(some2,"face");
    printf("%s ",some1);
    printf("%s\n",some2);
}

Please, could anyone spot some light on what's going on when memory is being allocated.

+7  A: 

You allocate one byte, then overrun the bounds of your allocated memory. sprintf does no bounds checking (its friend, snprintf does bounds checking).

When you overrun your allocated memory, you get undefined behavior, so anything can happen. In your case, it appears to work correctly. Your program could also crash, or anything else might happen.

James McNellis
that's what I thought. But the program prints "cool face" after execution.
facha
Compile with different optimization flags and watch what happens. Betcha something different occurs.
Michael Dorgan
There's no requirement for the program to output anything different. The programmer needs to make sure that the right thing is taking place. (In the case of modern computers, an 8-byte or larger chunk will actually be allocated, but you shouldn't depend on this.) If you want to have your sprintf's bounds-checked, use `snprintf(some1, 1, "cool");` instead. Note the 'n' in the name.
dash-tom-bang
@facha: The memory that "ool" and "ace" are written to is just memory. Even though the heap memory book keeping don't know that you're using it, and in fact you could be doing damage by using it, there isn't anything stopping you from using it. That being said, most operating systems on modern computers do keep up with a program's memory in large chunks and can tell if you get way out of bounds. With off by one or off by a few errors in writing to memory you are move likely to just end up with weird behavior of your program if anything bad happens at all.
nategoose
+7  A: 

You are invoking undefined behavior. Absolutely anything can happen at this point, including what you might expect.

What's actually happening is that the system does allocate memory to you in larger chunks. So while you're outside of the bounds as defined by your program, you haven't overstepped the buffer as far as the system goes. Almost all implementations do this; it's easier for the system to keep track of 16 byte chunks, say, than it is to do so on a byte-by-byte basis.

Matt B.
+1  A: 

Undefined behavior!

Especially in a debug build, malloc() will usually round up any allocation request to a reasonable boundary. But you are not allowed to rely on this behavior, and just because it works for you in a test program today doesn't mean it will work in a real-world program.

Daniel Pryden
+1  A: 

You are allocating "at least" 1 character for your array and then dropping 5 characters into it (4 for the string, 1 for the \0). You are usually overwriting memory outside of your array and that isn't a very good idea.

The reason it works is you are getting (un)lucky in that nothing else is being clobbered.

Michael Dorgan
A: 

Usually an operating system will give you more than you ask for just for simpler bookkeeping or whatever other reasons there are. The behaviour of a program is undefined if you use more than the amount that you requested.

Use a program like Valgrind and it'll tell you that you've done something wrong.

dreamlax