3

I have this simple test C program which leaks 4 bytes of memory:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int* x = malloc(sizeof(int));
    printf( "Address: %p\n", x);
    return 0;
}

I compile it with gcc -o leak leak.c, and then run it:

$ leak
Address: 0x55eb2269a260

Then I create another test C program that will try to free the leaked memory:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *addr = (void*)0x55eb2269a260;
    printf( "Trying to free address: %p\n", addr);
    free(addr);
    return 0;
}

I compile it with gcc -o myfree free.c and then run it:

$ myfree
Trying to free address: 0x55eb2269a260
Segmentation fault (core dumped)

What is happening here? Why is it not possible to free the leaked memory?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • 3
    Once the process ends, the memory is freed. Practically, it’s not a memory leak in that program. Processes can’t access each other’s memory without explicit cooperation anyway. – Ry- Aug 20 '19 at 10:27
  • 3
    On modern protected operating systems (like Linux which you seem to be using, you should really specify that), the memory map of one process is unique to that process only. – Some programmer dude Aug 20 '19 at 10:29
  • @Someprogrammerdude Yes I am on Ubuntu 19.04, linux. – Håkon Hægland Aug 20 '19 at 10:37
  • See also [When you exit a C application, is the malloc-ed memory automatically freed?](https://stackoverflow.com/q/2213627/2173773) – Håkon Hægland Aug 20 '19 at 10:55
  • Also see [Process isolation](https://en.wikipedia.org/wiki/Process_isolation), [Process isolation on Linux?](https://stackoverflow.com/q/56175076/608639) and [Does Linux support memory isolation for processes?](https://stackoverflow.com/q/39753607/608639) – jww Aug 20 '19 at 11:47

3 Answers3

2

Assuming we are talking about Unix-like operating systems (this also applies to Windows and the majority of other modern operating systems)...

What is happening here? Why is it not possible to free the leaked memory?

First of all: every running process have it's own virtual address space (or VAS). This VAS is a way the operating system have to lay out and organize the physical memory between different processes. It ranges from 0x0 to 0xFFFFFFFF on 32 bits processors and contains all the memory of the process - its code, static data, stack, heap, etc, it is all in the process VAS. A virtual address (or VA) is a specific address inside the virtual address space.

When you allocate memory with malloc the system will search for a valid unallocated memory on the process heap and if it finds, return a pointer of it (i.e. malloc essentially returns a virtual address).

After the process ends its VAS will be automatically "freed" by the operating system, so that memory is no longer valid, or allocated in that matter. Asides that, each process have its own virtual address space. You can not directly access a process VAS (virtual address space) using a VA (virtual address) of another process - by doing that what you actually end up doing is trying to access that VA in the running process which in your example is very likely to result in an unhandled ACCESS_VIOLATION exception and crashes the process.

andresantacruz
  • 1,676
  • 10
  • 17
  • So the memory is lost forever? It is not possible to free it even if you know the address? – Håkon Hægland Aug 20 '19 at 10:31
  • Yes, when the process ends its memory space is freed by the operating system, effectively whatever data was stored in that process' memory is "lost forever". – andresantacruz Aug 20 '19 at 10:33
  • @dedcos Ok, but it is possible to reallocate it by malloc? – Håkon Hægland Aug 20 '19 at 10:36
  • @HåkonHægland you can't give to `malloc` a specific address for it to alloc, and even if you could you were trying to access a `RVA` of process A in process B. – andresantacruz Aug 20 '19 at 10:38
  • @HåkonHægland there is a fundamental difference between the piece of memory in the RAM actually allocated by the operating system and the pointer you get as return from `malloc`. – andresantacruz Aug 20 '19 at 10:39
  • @HåkonHægland what you get from `malloc` is a Relative Virtual Address - it is just an offset of the process memory space used by the operating system to layout the memory. The actual address of that chunk allocated by `malloc` is managed only by the operating system. – andresantacruz Aug 20 '19 at 10:41
  • When I said `RVA` I actually meant to refer to `VA` (virtual address)! – andresantacruz Aug 20 '19 at 10:45
  • Is the memory freed by the OS even if the program crashes? – Håkon Hægland Aug 20 '19 at 10:51
  • @HåkonHægland yes. A program doesn't just crash. Every crash is caused by an unhandled exception and it's all well managed by the operating system. When you get a "segment fault" as you said in the question it is actually the operating system signaling to the process that that `VA` is not valid for the given operation. If the program doesn't consume and handle this exception, then the operating system ends this process execution abruptly. – andresantacruz Aug 20 '19 at 10:55
1

Each process has its own virtual memory space due to process isolation. Memory addresses in one process are not the same memory addresses in another process. You cannot just access dynamic memory by the address in another process.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Renat
  • 7,718
  • 2
  • 20
  • 34
1

Just to complete the answer of dedecos, the virtual address space of a process is always different for a different process in the same machine. This means that what for process A is at 0x55eb2269a260, in process B has no counterpart. No address at Process B matches the same memory as it does for process A. So then, it's impossible to address from B any of the addresses of process A.

The thing is that there is a memory manager at the operating system kernel that handles processes memory to be always disjoint, so even if two processes have the same variable at the same address, those variables are different (e.g. two versions of ls command executing at the same time will have the data segment at the same address, as the linker put it there) their address spaces (the same data addresses, for example) map to different memory pages for each process. This way, you can run the same program several times in parallel without clashing their data segments.

Operating systems offer ways for two processes to share a memory segment, so they can share common data, but even in that case, the addresses of both visuals of the same segment haven't to be placed at the same address (as one of those processes can have occupied the address given to the other for something else), so the conclusion is that what an address means for a process is not valid outside it.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31