-2

In C, I encountered an error when I coded the following example:

int *pointer;
int i = 0;
pointer = malloc(10 * sizeof(int));
pointer[i - 1] = 4;

Clearly i is a negative index into pointer.

Even if the incorrect piece memory was altered, why was an error only triggered upon free(pointer) [later on in the code]? The error was: double free or corruption (out).

EDIT: The compiler used was gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

jaynp
  • 3,275
  • 4
  • 30
  • 43
  • 6
    More than likely, heap membership, block size, and other info is kept in the memory immediately *prior* to the returned address from `malloc()`. Overwriting this data to corruption will not change ability to use the actual block. Rather, when it is needed (during a free) the corruption is encountered and will rear its ugly head. But **this is *entirely* implementation dependent**. – WhozCraig Feb 10 '13 at 05:31
  • 6
    If you do silly things expect silly behaviour. In this case you are modifying memory that does not belong to you. So you should expect the unexpected. – Ed Heal Feb 10 '13 at 05:35
  • I think this link would be a good reference: http://stackoverflow.com/questions/1119134/how-do-malloc-and-free-work – Ganesh Feb 10 '13 at 06:19
  • "I stepped on the rails when I saw the train coming. Please explain why my legs have been cut off only when the train arrived and not before." –  Feb 10 '13 at 06:41

2 Answers2

5

Most if not all memory managers (eg: malloc) allocate extra data around the memory you've requested. This extra is to help the memory manager manage the various allocations by adding some of its own data to the allocation. When you did your negative index, you overwrote this extra data. It's not invalid memory per se, so the CPU can't protect against it, but malloc will indeed complain when it sees that its data has been borked. That will occur on free().

PQuinn
  • 992
  • 6
  • 11
  • ["per se" :)](http://en.wiktionary.org/wiki/per_se) . Otherwise great answer, +1. – us2012 Feb 10 '13 at 05:34
  • 3
    The crucial works missing in this answer are: **Undefined Behavior(UB)**. Accessing an memory location that does not belong to you is UB. The UB occurred when the out of bounds memory location was accessed, what happens after that is purely undefined. It may or may not crash or burn the disc. No behavior is guaranteed. – Alok Save Feb 10 '13 at 05:43
  • @Alok, very true. Just luck that free() caught this. – PQuinn Feb 10 '13 at 05:45
1

Fundamentally, accessing pointer[-1] the way you did yields Undefined Behavior; in theory, anything could happen. But in practice, there’s a good explanation for the particular error message you got.

Recall that malloc has to save the size of the allocated chunk of memory somewhere so that free can work correctly. On some systems — and it seems yours is among that bunch — this information is stored in memory just before the address that malloc returns. (It might be interesting to print out that value, if you want to learn about your system’s implementation.)

When you overwrote that chunk of memory, you left the internals of the malloc-free system in an inconsistent state, leading free to report an error when this was discovered. The most likely time for such a discovery, of course, is when the memory management functions are called about this area of memory. (Some malloc corruptions will be detected the next time you call malloc, but that usually takes more deliberate effort to achieve.) Calling realloc should give you a similar error message.

J. C. Salomon
  • 4,143
  • 2
  • 29
  • 38