0

I'm working on OS X. I've written a simple code like

pTest       =   (char*)malloc(sizeof(char) * 3);

pTest[0]    =   0;
pTest[1]    =   1;
pTest[2]    =   2;

pTest       =   (char*)realloc(pTest, sizeof(char) * 2);

printf("%d %d %d %d\n", pTest[0], pTest[1], pTest[2], pTest[3]);
pTest[3]    =   100; // memory access violation.

If this code does not cause access violation, Why does realloc need? Although we are allocated memory in the heap segment with a small size, all we have to do is access to a further index such as pTest[100], pTest[2048], and pTest[65536].
Could someone explain why does not cause access violation?

inherithandle
  • 2,614
  • 4
  • 31
  • 53
  • 1
    You don't have to cast the void pointer to (char*) that is returned by malloc in c. – hetepeperfan Aug 01 '13 at 09:04
  • 1
    It all depends on the implementation of malloc. This is just a side effect. Accessing outside the bounds of what you have allocated is undefined behavior, which can cause many things including but not limited to, segmentation faults, heap corruption, disk reformatting and RAM melting. – Nbr44 Aug 01 '13 at 09:05
  • 1
    Yeah as already stated it's *undefined behaviour* but rarely a memory access violation. It all depends on where the memory was allocated. – trojanfoe Aug 01 '13 at 09:06
  • 1
    It is a bit like parking your car on the parking place of your neighbor, he might not notice it, or might decide to park his car there(crashing into yours), you just don't know what is going to happen. – hetepeperfan Aug 01 '13 at 09:10
  • `sizeof(char)` is 1 per definition, so you can omit it. – glglgl Aug 01 '13 at 09:25
  • Answer to similar question: http://stackoverflow.com/a/6445794/139746 – Pascal Cuoq Aug 01 '13 at 12:08

5 Answers5

4

void *realloc(void *ptr, size_t size);

The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes.

You are reducing size:

pTest   =   (char*)realloc(pTest, sizeof(char) * 2);
                                      ^
                                      | 
                                     changed size of array to two chars only

After this max index value can be 1 as pTest[1].

Any index value > 1, cause memory violation - illegal memory access - Undefined behavior at run time.

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
3

What you are doing there is undefined behaviour. It 'might' accvio, it might segfault. On the other hand it might email your cat. You can't rely on undefined behaviour, because it is undefined.

Salgar
  • 7,687
  • 1
  • 25
  • 39
0

First you use mealloc have a memory store 0,1,2 in heap.

Then you use realloc(pTest sizeof(char )*2); It cut the memory, only have 0,1 now.

When you print pTest[3], you already read data from freed memory. Maybe the memory still not use and just stay old value,but it is not safe.

Then you give a value to pTest[3]. but do you realize you only have a array size 2? you only can use pTese[0] and pTest[1]!

I fixed your code :

pTest       =   (char*)malloc(sizeof(char) * 3);

pTest[0]    =   0;
pTest[1]    =   1;
pTest[2]    =   2;

pTest       =   (char*)realloc(pTest, sizeof(char) * 4);// at lest 4 

printf("%d %d %d \n", pTest[0], pTest[1], pTest[2]);//  pTest[3]) is still unkonw;
pTest[3]    =   100; //it is ok now
Lidong Guo
  • 2,817
  • 2
  • 19
  • 31
0

Accessing outside of allocated memory is undefined. You typically won't get an access violation until you hit a segment boundary of some sort. Otherwise, as stated, the behavior is undefined.

Stay within your index boundaries when working with arrays. If you need access violation warnings for array index values, you have to add them yourself.

Also, your realloc is only giving a clue to the memory manager that you don't need the last byte you originally allocated. The memory manager may return the same pointer value or some other new pointer value. Your only concern is that you are not to exceed memory allocation. If you do, then undefined behavior will result, sometimes much later in the application.

0

It completely depends where the memory allocator takes the memory from and in which sizes.

Usually, the memory is taken from the end of the "normal" heap space, which is extended as needed. After freeing, there is a certain hysteresis in order to not immediately free everything we could, in order to minimize the number of calls to the OS.

Additionally, if the memory is not at the end of the heap, the freed memory will just be added to the memory region available for malloc(). It might change its content in order to be part of a linked list managing the free memory, but reading accesses will succeed as it is part of the memory assigned to the process.

Onliy if I have quite a big portion at the end of the heap, whose free() causes the heap to actually shrink, or if the memory block is so large that it was alloced via mmap(), access to it after free() will actually result in an access violation.

glglgl
  • 89,107
  • 13
  • 149
  • 217