Possible memory leak with malloc() - c++

I have this code:
#include <malloc.h>
int main()
{
int x = 1000;
//~600kb memory at this point
auto m = (void**)malloc(x * sizeof(void*));
for (int i = 0; i < x; i++)
m[i] = malloc(x * sizeof(void*));
for (int i = 0; i < x; i++)
free(m[i]);
free(m);
//~1700kb memory at this point
return 0;
}
When program starts memory consumption is about ~600kb, and when it ends ~1700kb. Is it memory leak or what?

malloc() acquires memory from the system using a variety of platform-specific methods. But free() does not necessarily always give memory back to the system.
One reason the behavior you're seeing might exist is that when you first call malloc() it will ask the system for a "chunk" of memory, say 1 MB as a hypothetical example. Subsequent calls will be fulfilled from that same 1 MB chunk until it is exhausted, then another chunk will be allocated.
There is little reason to immediately return all allocated memory to the system just because the application is no longer using it. Indeed, the most likely possibilities are that (a) the application requests more memory, in which case the recently freed pieces can be doled out again, or (b) the application terminates, in which case the system can efficiently clean up all its allocated memory in a single operation.

Is it memory leak or what?
No. You have each malloc matching a free and if I dont miss something you have no memory leak.
Note that what you see in the process manager is the memory assigned to the process. This is not necessarily equal to the memory actually in use by the process. The OS does not immediately reclaim it when you call free.
If you have a more complex code you can use a tool like valgrind to inspect it for leaks. Though, you better dont use manual memory managment at all, but use std containers instead (eg std::vector for dynamic arrays).

free() and malloc() are part of your Standard Library and their behavior is implementation dependent. The standard does not require free() to release once acquired memory back to your Operating System.
How the memory is reserved is plattform specific. On POSIX systems the mmap() and munmap() system calls can be used.
Please Note that most Operating Systems implement Paging, allocating memory in chunks to processes anyway. So releasing each single byte would only pose a performance overhead.

When you are running your application under management of operating system, the process of memory allocation in languages like C/C++ is two-fold. First, there is a business of actually requesting memory to be mapped into process from operating system. This is done through OS-specific call, and an application needs not bothering about it. On Linux this call is either sbrk or mmap, depending on several factors. However, this OS-requested memory is not directly accessible to C++ code, it has no control over it. Instead, C++ runtime manages it.
The second thing is actually providing a usable pointer to C/C++ code. This is also done by runtime when C++ code asks for it.
When C/C++ code calls malloc(or new), C++ runtime first determines, if it has enough continuous memory under it's management to provide a pointer to it to application code. This process is further complicated by efficiency optimizations inside malloc/new, which usually provide for several allocation arenas, used depending on object sizes, but we won't talk about it. If it has, the memory region will be marked as used by application, and a pointer will be returned to the code.
If there is no memory available, a chunk of memory would be requested from the OS. The size of the chunk normally will be way bigger than what was requested - because requesting from OS is expensive!
When the memory is deleted/freed, C++ runtime reclaims it. It might decide to return memory back to OS (for example, if there is a pressure in terms of total memory consumption on the machine), or it can just store it for future use. Many times memory will never be returned to the OS until process exits, so any OS-level tool will show process consuming memory, even though the code delete'd/freed it all!
It is also worth noting that usually application can request memory from OS bypassing C++ runtime. For example, on Linux it could be done through mmap call or, in bizarre cases, through sbrk - but in latter case you won't be able to use runtime memory management at all after this. If you use those mechanisms, you will immediately see process memory consumption growing or decreasing with every memory request or return.

Related

Why does the free() function not return memory to the operating system?

When I use the top terminal program at Linux, I can't see the result of free.
My expectation is:
free map and list.
The memory usage that I can see at the top(Linux function) or /proc/meminfo
get smaller than past.
sleep is start.
program exit.
But
The usage of memory only gets smaller when the program ends.
Would you explain the logic of free function?
Below is my code.
for(mapIter = bufMap->begin(); mapIter != bufMap -> end();mapIter++)
{
list<buff> *buffList = mapIter->second;
list<buff>::iterator listIter;
for(listIter = buffList->begin(); listIter != buffList->end();listIter++)
{
free(listIter->argu1);
free(listIter->argu2);
free(listIter->argu3);
}
delete buffList;
}
delete bufMap;
printf("Free Complete!\n");
sleep(10);
printf("endend\n");
Thanks you.
Memory is allocated onto a heap.
When you request some memory in your program (with a new() or malloc() etc.) Your program requests some memory from its heap, which in turn requests it from the operating system{1}. Since this is an expensive operation, it gets a chunk of memory from the OS, not just what you ask for. The memory manager puts everything it gets into the heap, just returning to you the perhaps small amount you asked for. When you free() or delete() this memory, it simply gets returned to the heap, not the OS.
It's absolutely normal for that memory to not be returned to the operating system until your program exits, as you may request further memory later on.
If your program design relies on this memory be recycled, it may be achievable using multiple copies of your program (by fork()~ing) which run and exit.
{1} The heap is probably non-empty on program start, but assuming it's not illustrates my point.
The heap typically uses operating system functions to manage its memory. The heap’s
size may be fixed when the program is created, or it may be allowed to grow. However,
the heap manager does not necessarily return memory to the operating system when
the free function is called. The deallocated memory is simply made available for subsequent use by the application. Thus, when a program allocates and then frees up memory, the deallocation of memory is not normally reflected in the application’s memory
usage as seen from the operating system perspective.

Can a graceless exit corrupt the C++ memory allocator?

It is well known that the usual cause of a std::bad_malloc being thrown is when memory is exhausted.
I'm executing an embedded, bare metal (without Operating System) application. The initial allocation sometimes succeeds, and sometimes fails. Since there is no other code running (no OS, no other processes), I have good reason to believe that this std::bad_alloc is more complex than allocating more memory than is available to the system. When it works, there is ~500kB of memory allocated. The hardware has been allocated 16MB.
Instead, it seems that the system has an incorrect record of how much memory is allocated, specifically that when the allocator begins, it thinks some non-zero amount of memory has already been allocated.
When a bare metal application starts, it should have identically zero memory allocated. It seems that is not the case here.
Is it possible that some state in the memory allocator is being retained between soft resets? How can I find out how the allocation is being done?
This is running on an ARMv7 with gcc (Sourcery CodeBench Lite 2013.05-40) 4.7.3, and linking against libstdc++6.0. We are compiling with -O0 -g.
We are allocating both std:: objects and user-defined objects with the new keyword, and the standard allocator.
If state is retained between restarts, then this is most likely due to incorrect initialisation at start-up.
It is the responsibility of the C++ runtime start-up to initialise the standard library. In a bare-metal system this includes initialising the heap and memory allocator. How this is done, and whether you have to perform any special action will depend on your particular tool-chain and library.
In ARM RealView (also used by Keil MDK-ARM) for example, you normally specify the heap size explicitly in the start-up code configuration. In other cases it is common for the linker script to automatically allocate all available memory that is not statically allocated or allocated to the stack to be allocated to the heap automatically. The linker script still needs to know the location and size of available RAM of course. Check your linker's map file output to verify the size and location of the heap.
Most embedded system libraries include stubs that must be user-implemented to match the library to the target - mostly this is related to I/O, but in the Newlib library (often used with GCC bare-metal toolchains) for example, the sbrk (or sbrk_r) stub must be reimplemented for correct heap operation. The implementation of sbrk is critical to the correct operation of the heap.
Added
It appears that Sourcery CodeBench Lite uses Newlib. I have seen implementations that start as follows:
caddr_t _sbrk(int incr)
{
extern char _ebss; // Defined by the linker
static char *heap_end;
char *prev_heap_end;
if (heap_end == 0) { ...
This is potentially unsafe if the runtime initialisation does not correctly initialise static data to zero (some embedded systems do that for faster start-up; though it is seldom worth the potential for bugs). Verify that your start-up performs zero-initialisation correctly and in any case explicitly initialise heap_end to zero:
static char *heap_end = 0 ;
in order to guarantee that it will work regardless of the strict correctness or otherwise of the start-up.
A good implementation of memory allocation should not get corrupted by allocating all available memory (or trying to allocate more than all) , such that std::bad_alloc is called. It is of course possible that there are bugs in the memory allocator in the OS you are using - there is no telling. But a "good" allocator should not get corrupted or stop working simply because your application allocated until it got std::bad_alloc.
However, whether just exiting the application with exit(1) at that point will free up the memory allocated by the application code or not depends on your operating system. If it handles cleanup of exiting application code, then you're safe. If the OS doesn't, then you need to catch the exception and clean everything up yourself. Since there are literally many hundreds of operating systems in existance, it's impossible to answer the question in a general way.
It should be pretty easy to test this: Just write an application that allocates a lot of memory in a loop, run it several times times and determine if the number of iterations in the loop is about the same number or, for example, reduces for each run of the application - in the latter case, you have some sort of problem.

Can we access dangling pointer /access other process memory similar to anti-virus? Would memory leak be possible for such inter-process access?

I was always under the impression that trying to access a dynamically freed (first allocated and later deleted/freed) memory would end up with a coredump.
However when I executed the below code it went through successfully.
int* ptr = new int(3);
delete ptr;
cout << "value : " << *ptr << " " << ptr;
So I went ahead and created a dangling pointer and explicitly tried to access the memory, but now it dumped.
int* aptr;
aptr = (int*)0x561778;
cout << "value : " << *aptr << " " << aptr;
1) If we cannot access a memory beyond a given process space, then how is it that I was able to access the memory after I freed/released it? ( First example )
Also, If that's the case then how do anti-viruses scan the memory allocated by other processes?
2) If I dynamically allocate but don't free the memory, then it would cause memory leak.
But what if my entire process was killed? or completed execution, so got closed.
Then wouldn't OS ensure to clean up all the resources allocated to this process? So would memory leak occur only for processes which are on a long run?
If this is true, then when I explicitly try to access the contents of another process how would an OS ensure that it doesn't free up this memory?
1) If we cannot access a memory beyond a given process space, then how
is it that I was able to access the memory after I freed/released it?
( First example )
Because the C or C++ runtime keeps a "heap" of memory, and when you call free or delete, the memory is not actually rendered unusable to the process, it is simply put back into the "free memory" region of the heap, so it will be re-used. This is done because it's very common for a process to allocate some memory, free it, allocate some again, free it, etc. For example
void readfile(const std::string& fname)
{
std::ifstream f(fname.c_str());
std::string* content = new std::string;
while(cin.getline(content))
{
...
}
delete content;
}
This function (stupidly, because we should not allocate a std::string) will first allocate space for std::string, and then space for the content [possibly in several portions] inside std:string when the getline call is reading the file. There may be other memory allocations in for example `std::ifstream too.
The heap is designed to minimise the number of times it asks the OS to map/unmap memory from the global physical memory to a particular process, since it's quite "expensive" in terms of performance to map and unmap virtual memory in nearly all processors (in particular, unloading the now defunct memory pages from other cores will involve sending a message to the other processor, the other processor stopping what it's currently doing, updating it's virtual mappings, and then answering back "I've done that", before continuing where it was). And of course, if the OS doesn't unmap the memory of the process when the process stops using it, that same process could indeed "use" that memory address to find content of other processes - which would be a bad thing, so the OS will force all processor cores to give up it's memory mappings before that bit of memory can be used again for another process [at least].
Edit: To clarify, the heap will sometimes release memory back to the OS. For example, if you make a LARGE allocation, and then free that same allocation, it may well unmap that immediately, and thus you wouldn't be able to access the memory after it has been freed. Any access of memory after it has been freed is undefined behaviour, the runtime can (and quite often will) do anything it likes with the memory at that point. The most common scenarios are:
Just keep it as it is, but put it in the "freed" pile.
Keep it around as freed memory, but fill it with some "magic" pattern to detect when it has been written to, so "use after free" can be detected (very good thing to detect!)
The memory is unmapped, and no longer available to the current process.
The memory is almost immediately allocated for another purpose, and used again.
The same OS can at different times use any of these scenarios, in almost any order.
Also, If that's the case then how do anti-viruses scan the memory
allocated by other processes?
Completely different question. They use either debug interfaces to read another process's memory, or their own kernel driver functionality that uses kernel functions that allow any process to read any other process's memory - after all, the kernel can do anything. [Actually, fairly often, the anti-virus software is more interested in what is being loaded into memory from a file, so apply file access filters that examine reads/writes of data to/from files, rather than scanning what is in memory]
2) If I dynamically allocate but don't free the memory, then it would
cause memory leak. But what if my entire process was killed? or
completed execution, so got closed. Then wouldn't OS ensure to clean
up all the resources allocated to this process? So would memory leak
occur only for processes which are on a long run?
A process' memory is freed when the process dies. Always, every time. Or you could cause a system to fail by starting a process that allocates a fair amount of memory, kill it on purpose, run it again, kill it, run, kill, etc. That would be a bad thing, right?
You can of course have a very quick memory leak. Try:
std:string str;
str.append(100000, 'x');
std::vector<std::string> v;
int i = 0;
while(1)
{
std::cout << "i=" << i << std::endl;
v.push_back(str);
It won't take that many seconds before the system starts swappng, and a little while later it will be killed (if you don't get bored and kill it first). Expect a linux system to get fairly unresponsive if you do this...
If this is true, then when I explicitly try to access the contents of
another process how would an OS ensure that it doesn't free up this
memory?
A normal process will not be able to access memory that belongs to another process - only through limited interfaces such as debug interfaces or specially written kernel drivers can you do this. Or by using OS-supported shared memory, where the same memory is mapped into two different processes with the permission of the OS, of course.
These methods of accessing memory of another process will involve some form of "reference counting" [in fact the same applies for example if the process is currently in a system call trying to save a 1000MB file, and the process is for one reason or another killed - say another thread causes a unrecoverable fault] - the OS keeps track of how many "users" there are of a given piece of memory, so that it doesn't pull the rug from under the feet of some process [or itself].

Why does malloc() or new never return NULL? [duplicate]

This question already has answers here:
SIGKILL while allocating memory in C++
(2 answers)
Closed 9 years ago.
I'm writing an application which needs a lot of memory for caching purposes as I described he here. Now I'm playing around with some malloc / new constructions to figure out how I could realise it. I made a strange observation:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
while(1) {
char *foo = (char*)malloc(1024);// new char[1024];
if(foo == NULL) {
printf("Couldn't alloc\n");
fflush(stdout);
return 0;
}
}
return 0;
}
Why does that printf never be reached? If my system runs out of memory, malloc is said to return NULL, as it is explained here. But I always receive SIGKILL (I'm using linux...).
Linux, by default, usually uses an opportunistic memory allocation scheme, meaning the kernel will give you a valid address that won't be allocated until first use.
See:
SIGKILL while allocating memory
C Program on Linux to exhaust memory
According to those responses you can turn this feature off using echo 2 > /proc/sys/vm/overcommit_memory.
From what I can tell, this is done under the assumption that you wont necessarily use all the memory that you allocate. I can't say that I personally ever allocate space that I don't touch at least once, so I'd be curious to know how this affects real life performance...
Regarding the SIGKILL failure, every malloc you call is still allocating some memory for each call. Eventually you will likely fill your memory with malloc overhead and thus evoke the fury of the out of memory kill feature. Whether this alone is the issue or if perhaps the overcommit policy still allocates some fraction of the requested space is a good question.
Usually, Linux will allocate as much (virtual) memory as you request, and only allocate physical memory for it when it's needed. If the system runs out of physical memory, then it starts killing processes to free some.
This means that malloc will succeed unless the request is ludicrous, but your process (or some other) is likely to get killed as the memory is used.
For more details, see the manpage for malloc, and its references:
By default, Linux follows an optimistic memory allocation strategy.
This means that when malloc() returns non-NULL there is no guarantee
that the memory really is available. In case it turns out that the
system is out of memory, one or more processes will be killed by the
OOM killer. For more information, see the description of
/proc/sys/vm/overcommit_memory and /proc/sys/vm/oom_adj in proc(5), and
the kernel source file Documentation/vm/overcommit-accounting.
(And of course new won't return null anyway unless you use the no-throwing version).
malloc returns NULL if requested allocation cannot be fulfilled. But maybe you should try allocating tons of space from heap.
See here.
On linux, the only way to get an error when calling malloc() is to
disable memory-overcommiting. On regular linux systems, this is the
only way for malloc() to return NULL. If an icecast process reaches
that point, it's screwed anyway it won't be able to do anything
meaningful: any source reads will fail (refbuf alloc), any log print
will also fail (printf uses malloc too), so it might as well give up and
call abort().
Malloc would return NULL, if the operating system let your program run that long. But before malloc gets a chance to run the operating system kills your process.
Just like it kills your process if it detected that you were writing outside memory pages allocated to your process.

Is heap memory per-process? (or) Common memory location shared by different processes?

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 heap memory per-process?
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.
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.)
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.
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.
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.
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.
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).