views:

136

answers:

6

Every process can use heap memory to store and share data within the process. We have a rule in programming whenever we take some space in heap memory, we need to release it once job is done, else it leads to memory leaks.

int *pIntPtr = new int;
.
.
.
delete pIntPtr;

My question is, will the heap memory exist when the application/process is closed?

If YES,

then memory leak is possible only when a process is in running state.

If NO,

then it means OS is able to retain data in a memory somewhere. If so, is there a way to access this memory by another process. Also this may become a way for inter-process communication.

I suppose answer to my question is YES. Please provide your valuable feedback.

+1  A: 

In most modern operating systems each process has its own heap that is accessible by that process only and is reclaimed once the process terminates - that "private" heap is usually used by new. Also there might be a global heap (look at Win32 GlobalAlloc() family functions for example) which is shared between processes, persists for the system runtime and indeed can be used for interprocess communications.

sharptooth
AFAIK memory allocated with GlobalAlloc cannot be shared to other processes any more. It was superseded with file mapping.
adf88
@adf88: If true, that makes the name of the function quite amusing, to my limited mind. :)
unwind
MSDN: "Memory objects allocated by GlobalAlloc and LocalAlloc are in private, committed pages with read/write access that cannot be accessed by other processes. Memory allocated by using GlobalAlloc with GMEM_DDESHARE is not actually shared globally as it is in 16-bit Windows. This value has no effect and is available only for compatibility. Applications requiring shared memory for other purposes must use file-mapping objects. Multiple processes can map a view of the same file-mapping object to provide named shared memory"
adf88
A: 

Generally the allocation of memory to a process happens at a lower level than heap management.

In other words, the heap is built within the process virtual address space given to the process by the operating system and is private to that process. When the process exits, this memory is reclaimed by the operating system.

Note that C++ does not mandate this, this is part of the execution environment in which C++ runs, so the ISO standards do not dictate this behaviour. What I'm discussing is common implementation.

In UNIX, the brk and sbrk system calls were used to allocate more memory from the operating system to expand the heap. Then, once the process finished, all this memory was given back to the OS.

The normal way to get memory which can outlive a process is with shared memory (under UNIX-type operating systems, not sure about Windows). This can result in a leak but more of system resources rather than process resources.

paxdiablo
+3  A: 

On almost every system currently in use, heap memory is per-process. On older systems without protected memory, heap memory was system-wide. (In a nutshell, that's what protected memory does: it makes your heap and stack private to your process.)

So in your example code on any modern system, if the process terminates before delete pIntPtr is called, pIntPtr will still be freed (though its destructor, not that an int has one, would not be called.)

Note that protected memory is an implementation detail, not a feature of the C++ or C standards. A system is free to share memory between processes (modern systems just don't because it's a good way to get your butt handed to you by an attacker.)

Jonathan Grynspan
+1: for specifying that this is not a language feature but an OS implementation choice.
ereOn
Why thank you, good sir. :D
Jonathan Grynspan
So long as we're being pedantic, ISO C Standard does not refer to "heap" at all, and ISO C++ does it only in the context of `std::make_heap` and related STL algorithms. The correct standarteze for this is rather "dynamic storage duration". So "heap" itself is strictly an implementation detail and not a language feature; from which, of course, follows that any properties of said heap are also an implementation detail.
Pavel Minaev
True; however, "heap" is easier to type. ;p
Jonathan Grynspan
I don't think I've seen "heap" used in discussions of C very often. It seems to be limited to higher-level languages that fully abstract memory (C#, Java, PHP, and the like.) C++ discussions do see mentions of "the heap," but I still haven't seen it terribly often.
Jonathan Grynspan
I think this has to do with a person's programming specialties, more than anything. If you code in languages where you have bare-bones memory access (C, C++, Obj-C, memory management aside) you tend not to think of memory as an abstract thing far removed (the heap.) Whereas Java, etc. coders don't need to *care* about memory in the first place.
Jonathan Grynspan
@Pavel: if I may continue the pedantry, the C++ standard at least does refer to the "free store", which is equivalent to what people usually mean when they talk about "the heap" in the context of memory management. The data structure with the same name is unrelated (except perhaps historically), and I guess that's why the standard chose a different name.
Mike Seymour
A: 

Normally the O/S will reclaim any leaked memory when the process terminates.

For that reason I reckon it's OK for C++ programmers to never explicitly free any memory which is needed until the process exits; for example, any 'singletons' within a process are often not explicitly freed.

This behaviour may be O/S-specific, though (although it's true for e.g. both Windows and Linux): not theoretically part of the C++ standard.

ChrisW
If you're sure that memory is all that you've allocated, then perhaps. However, you have to be mindful that a constructed object might consume more resources than just memory. If so, then a destructor call right before process termination might be necessary to ensure appropriate cleanup.
csj
@csj The O/S (Windows) should recover *all* of a process's resources when the process ends: including e.g. any open file handles, mutexes, device handles, GDI objects, etc.
ChrisW
@ChrisW: and no known OS does that. Temporary files are probably the most common leaks. The handle is closed, yes, but the file remains on disk.
MSalters
@MSalters Do you know of any other kinds of "leak", apart from temp files?
ChrisW
@Chris: Shared memory mappings, child processes, TCP connections (will time out), ongoing non-atomic operations such as ShFileOperation with wildcards, ...
MSalters
+1  A: 

There are some special purpose operating systems that will not reclaim memory on process exit. If you're targeting such an OS you likely know.

Most systems will not allow you to access the memory of another process, but again...there are some unique situations where this is not true.

The C++ standard deals with this situation by not making any claim about what will happen if you fail to release memory and then exit, nor what will happen if you attempt to access memory that isn't explicitly yours to access. This is the very essence of what "undefined behavior" means and is the core of what it means for a pointer to be "invalid". There are more issues than just these two, but these two play a part.

Noah Roberts
A: 

For practical purposes, the answer to your question is yes. Modern operating systems will generally release memory allocated by a process when that process is shut down. However, to depend on this behavior is a very shoddy practice. Even if we can be assured that operating systems will always function this way, the code is fragile. If some function that fails to free memory suddenly gets reused for another purpose, it might translate to an application-level memory leak.

Nevertheless, the nature of this question and the example posted requires, ethically, for me to point you and your team to look at RAII.

int *pIntPtr = new int;
...
delete pIntPtr;

This code reeks of memory leaks. If anything in [...] throws, you have a memory leak. There are several solutions:

int *pIntPtr = 0;
try
{
    pIntPtr = new int;
    ...
}
catch (...)
{
    delete pIntPtr;
    throw;
}
delete pIntPtr;

Second solution using nothrow (not necessarily much better than first, but allows sensible initialization of pIntPtr at the time it is defined):

int *pIntPtr = new(nothrow) int;
if (pIntPtr)
{
    try
    {
         ...
    }
    catch (...)
    {
        delete pIntPtr;
        throw;
    }
    delete pIntPtr;
}

And the easy way:

scoped_ptr<int> pIntPtr(new int);
...

In this last and finest example, there is no need to call delete on pIntPtr as this is done automatically regardless of how we exit this block (hurray for RAII and smart pointers).

Thanks for teaching RAII at this point (which I happen know already by chance!)RAII is vital in writing exception-safe C++ code: to release resources before permitting exceptions to propagate (in order to avoid resource leaks) ONE CAN WRITE APPROPRIATE DESTRUCTORs once rather than dispersing and duplicating cleanup logic between exception handling blocks that may or may not be executed.
AKN