0

I wrote a function to add items to my log file. Variables loglevs[] and des together exceed 30 characters (by far). When I use the function as below, all works fine.

char *logitem (int loglev, const char *des) {

    extern const char *loglevs[];
    char *lld; // loglevel & description total 28 characters (7+1+20)

    lld = (char *) malloc((29) * sizeof(char));
    snprintf(lld, 29, "[%5s] %s", loglevs[loglev], des);

    return lld;

}

However when I use malloc(24) instead of malloc(29), I get the following error:

root@vm:/home/geohei/devel# prog
*** Error in `prog': malloc(): memory corruption: 0x0000000000853330 ***
Aborted (core dumped)

I was expecting to get the error already at malloc(28). Why is it only showing at malloc(24)? Actually, I can go down to malloc(25) before the error pops up.

I confirmed the test multiple times.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
geohei
  • 696
  • 4
  • 15

3 Answers3

4

It's undefined behaviour, which is defined in this online c standard draft as follows:

3.4.3

1 undefined behavior behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

So the program may do anything, even ignoring the situation. But it might also crash or call the police :-)

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
3

It is undefined behavior. Be scared of UB. malloc is just a standard library routine (which ask memory -in multiple of pages- to the kernel using some system call like mmap(2)). If you "overflow" the memory zone you have probably corrupted your heap memory.

But consider using tools like valgrind (and address sanitizers - e.g. with GCC).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
2

If you are asking WHY, there are all kinds of reasons why something like this might work. They depend upon the implementation.

Your malloc function might allocate memory behind the scenes in fixed sizes or it could allocate memory that is already rounded up to some value. Let us say for example that your malloc implementation always allocated in multiples of 8 bytes.

Then, your malloc(25) — malloc (29) calls might actually be allocating 32 bytes. So going beyond the end, might not be hurting you. When you go down to malloc (24) you might be going right off the end of the memory block.

We can only guess what what is actually happening here. The library is free to do as it wants within the bounds of the language specification.

As noted, the behavior here is completely undefined which is why you should not do this. A different library might give an entirely different result.

user3344003
  • 20,574
  • 3
  • 26
  • 62