I have created a sample application like below. I have a requirement to create 1024*1024 structs. Before calling the new operator my application is consuming some amount of memory (say 0.3mb). After calling the new operator the memory is increased (say 175mb). After calling the delete operator the memory is decreased (say 15mb). So finally there is a difference in the memory. I observed all these memory details from Task Manager. I am confused whether it should be considered as a memory leak, or will that memory slowly releases? If not, how can I free that remaining memory?
struct testSt
{
bool check;
std::string testString;
};
int main()
{
testSt *testObj = new testSt[1024 * 1024];
delete[] testObj;
return 0;
}
There is definitely no memory leak in your application. The reason the numbers before and after the allocation do not appear to match is that task manager tool is to coarse for the purposes of detecting memory leaks in a C++ program. Rather than recording the memory usage of only your code, it records all memory usage of the process that executes your code, including any memory used by the standard C++ library that supports your code's operations.
Use a memory profiler, such as valgrind, to test your code for memory leaks.
In addition, consider switching away from raw pointers for making containers. The best way by far to reduce the possibility of having a memory leak is to automate memory management using containers from the standard C++ library. In your case, defining a vector
std::vector<testSt> testObj(1024*1024);
would let you avoid allocation and deallocation altogether.
There is no memory leak in the posted code. The reason memory usage reported by task manager doesn’t go back to what it was is that the process’s runtime is keeping some of the allocated pages for later reuse, so it (hopefully) won’t have to bother the OS for more RAM the next time it wants to allocate an object. This is a normal optimization and nothing to be too concerned about. The real test for a leak would be to run your code in a loop for many iterations; if during that test you see your process’s memory usage increasing without bound, that would suggest there is a memory leak. If it levels off and then remains constant, on the other hand, that suggests there isn’t one.
You're code is correct, the array will be deleted.
You can test this with the following:
struct testSt
{
bool check;
std::string testString;
~testSt()
{
std::cout << "Destroyed!" << std::endl;
}
};
Are you running from the debugger? The additional memory may be held by the IDE.
Related
I have read this question and answer
dynamically allocated memory after program termination,
and I want to know if it is okay to NOT delete dynamically allocated memory and let it get freed by the OS after programme termination.
So, if I have allocated some memory for objects that I need thoughout the programme, is it ok to skip deleting them at the end of the programme, in order to make the code run faster?
The short answer is yes, you can, the long answer is possibly you better not do that: if your code needs to be refactored and turned into a library, you are delivering a considerable amount of technical debt to the person who is going to do that job, which could be you.
Furthermore, if you have a real, hard-to-find memory leak (not a memory leak caused by you intentionally not freeing long-living objects) it's going to be quite time consuming to debug it with valgrind due to a considerable amount of noise and false positives.
Have a look at std::shared_ptr and std::unique_ptr. The latter has no overhead.
Most sane OS release all memory and local resources own by the process upon termination (the OS may do it in lazy manner, or reduce their share counter, but it does not matter much on the question). So, it is safe to skip releasing those resources.
However, it is very bad habit, and you gain almost nothing. If you found releasing object takes long time (like walking in a very long list of objects), you should refine your code and choose a better algorithm.
Also, although the OS will release all local resources, there are exceptions like shared memory and global space semaphore, which you are required to release them explicitly.
First of all, the number one rule in C++ is:
Avoid dynamic allocation unless you really need it!
Don't use new lightly; not even if it's safely wrapped in std::make_unique or std::make_shared. The standard way to create an instance of a type in C++ is:
T t;
In C++, you need dynamic allocation only if an object should outlive the scope in which it was originally created.
If and only if you need to dynamically allocate an object, consider using std::shared_ptr or std::unique_ptr. Those will deallocate automatically when the object is no longer needed.
Second,
is it ok to skip deleting them at the end of the programme, in order
to make the code run faster?
Absolutely not, because of the "in order to make the code run faster" part. This would be premature optimisation.
Those are the basic points.
However, you still have to consider what constitutes a "real", or bad memory leak.
Here is a bad memory leak:
#include <iostream>
int main()
{
int count;
std::cin >> count;
for (int i = 0; i < count; ++i)
{
int* memory = new int[100];
}
}
This is not bad because the memory is "lost forever"; any remotely modern operating system will clean everything up for you once the process has gone (see Kerrek SB's answer in your linked question).
It is bad because memory consumption is not constant when it could be; it will unnecessarily grow with user input.
Here is another bad memory leak:
void OnButtonClicked()
{
std::string* s = new std::string("my"); // evil!
label->SetText(*s + " label");
}
This piece of (imaginary and slightly contrived) code will make memory consumption grow with every button click. The longer the program runs, the more memory it will take.
Now compare this with:
int main()
{
int* memory = new memory[100];
}
In this case, memory consumption is constant; it does not depend on user input and will not become bigger the longer the program runs. While stupid for such a tiny test program, there are situations in C++ where deliberately not deallocating makes sense.
Singleton comes to mind. A very good way to implement Singleton in C++ is to create the instance dynamically and never delete it; this avoids all order-of-destruction issues (e.g. SettingsManager writing to Log in its destructor when Log was already destroyed). When the operating system clears the memory, no more code is executed and you are safe.
Chances are that you will never run into a situation where it's a good idea to avoid deallocation. But be wary of "always" and "never" rules in software engineering, especially in C++. Good memory management is much harder than matching every new with a delete.
This question is as in title:
Is it possible to produce a memory leak without using any kernel specific means like malloc, new, etc?
What if I will make a linked list inside a function with lot of elements in there, and after it I'll exit from this function without cleaning a list. The list will be created without using any malloc calls, i.e.
struct list_head {
struct list_head *next, *prev;
}
Can it be guaranteed that all resources will be freed after exiting from this function? So I can freely execute it a million times and nothing will be leaked?
Subject: If you not using any particular malloc or new calls you won't get a heap memory leak. Never. Is that right?
A leak is always connected to a resource. A resource is by definition something that you acquire manually, and that you must release manually. Memory is a prime example, but there are other resources, too (file handles, mutex locks, network connections, etc.).
A leak occurs when you acquire a resource, but subsequently lose the handle to the resource so that nobody can release it. A lesser version of a leak is a "still-reachable" kind of situation where you don't release the resource, but you still have the handle and could release it. That's mostly down to laziness, but a leak by contrast is always a programming error.
Since your code never acquires any resources, it also cannot have any leaks.
The variables you applied without malloc or new is located at stack
space in the memory. So when the function returned, the variable is
taken back.
On the other hand, the memory you applied with malloc or new is
located at heap space. The system doesn't care whether you release the
space or not. In this situation, if you don't use free or delete,
memory leak will happen.
Subject: If you not using any particular malloc or new calls you won't get a heap memory leak. Never. Is that right?
That assumption is not entirely correct. The problem is that the operating system itself (or other third party components you have to rely on) can have memory leaks as well. In that case you might not actively call malloc, but call other (operating system) functions which could leak.
So your assumption depends on how strongly you consider such a thing. You can argue that the OS/third party implementation is outside your domain, then this assumption would be correct. If you have a well defined system and your requirements are such that you have to garuantee a certain uptime, something like this may have to be considered as well.
So the answer to this question ...
Is it possible to make memory leak without using malloc?
... is:
Yes, it is possible.
malloc() allocates memory from the heap, while space for string and struct literals (string1, string2 and those list_head's) will be reserved at compile time at the stack.
Actually any memory allocated for a program (heap or stack) will be reclaimed by the kernel when the process exits (at *nix system at least).
I would define memory leak as allocating memory on heap and without freeing it when your program exits. This definition actually answers your question.
There are standard functions (like strdup) that will allocate memory on heap, beware of them.
Another example of a resource that you can allocate and forget to free:
If you're using OpenGL, and you call glGenBuffers() a million times without the corresponding glDeleteBuffers calls, it's extremely likely that you will run out of VRAM and your graphics driver will start leaking to system memory.
I just had this happen. Fortunately, Visual Studio's memory profiler made it pretty easy to find. It showed up as a large number of allocations made by the external process nvoglv32.dll, which is my NVIDIA OpenGL driver.
I remember reading in a book on programming for computer games, sorry can't remember title. That an easy way to improve performance is do something like this near the start:
int main()
{
{
char dummy* = new char[10000000]; // 10Mbytes ish
delete[] dummy;
}
...
}
The idea is that the expensive part of dynamic memory allocation is the request to get memory from the OS, which doesn't normally get returned until the end of the program. Has anybody used this and seen performance improvements ?
Whether this works or not depends on the OS in question. A lot of modern OSes use mmap under the hood for large memory allocation and bypass the process's heap altogether. This means the allocation will be made directly from the OS and then returned directly to the OS when freed.
A much better strategy is to generally do your memory allocation at the start and reuse space allocated as much as possible before returning the memory to the heap. This is the logic behind STL allocators.
That doesn't make sense. You allocate a huge block, then free it and the heap takes ownership of the memory occupied by the block and can legally fragment it while it is used later.
That doesn't necessarily improve performance, as the current Standard says nothing about how the memory is dynamically allocated, deallocated and then reallocated. However, an implementation can make use of the same memory region in the rest of the program whenever it needs to allocate memory . It's more like memory pooling.
Anything could be possible. It entirely depends on implementation. Also it may even choose to remove the code altogether, as it does nothing.
Depending on your environment, there may be loader flags that let you specify an initial heap size. This memory will be allocated when your program is loaded into memory, so it becomes part of the start-up time. This should give the same results, with the benefit that the compiler won't optimize it away.
When instantiating a class with new. Instead of deleting the memory what kinds of benefits would we gain based on the reuse of the objects?
What is the process of new? Does a context switch occur? New memory is allocated, who is doing the allocation? OS ?
You've asked a few questions here...
Instead of deleting the memory what kinds of benefits would we gain based on the reuse of the objects?
That depends entirely on your application. Even supposing I knew what the application is, you've left another detail unspecified -- what is the strategy behind your re-use? But even knowing that, it's very hard to predict or answer generically. Try some things and measure them.
As a rule of thumb I like to minimize the most gratuitous of allocations. This is mostly premature optimization, though. It'd only make a difference over thousands of calls.
What is the process of new?
Entirely implementation dependent. But the general strategy that allocators use is to have a free list, that is, a list of blocks which have been freed in the process. When the free list is empty or contains insufficient contiguous free space, it must ask the kernel for the memory, which it can only give out in blocks of a constant page size. (4096 on x86.) An allocator also has to decide when to chop up, pad, or coalesce blocks. Multi-threading can also put pressure on allocators because they must synchronize their free lists.
Generally it's a pretty expensive operation. Maybe not so much relative to what else you're doing. But it ain't cheap.
Does a context switch occur?Entirely possible. It's also possible that it won't. Your OS is free to do a context switch any time it gets an interrupt or a syscall, so uh... That can happen at a lot of times; I don't see any special relationship between this and your allocator.
New memory is allocated, who is doing the allocation? OS ?It might come from a free list, in which case there is no system call involved, hence no help from the OS. But it might come from the OS if the free list can't satisfy the request. Also, even if it comes from the free list, your kernel might have paged out that data, so you could get a page fault on access and the kernel's allocator would kick in. So I guess it'd be a mixed bag. Of course, you can have a conforming implementation that does all kinds of crazy things.
new allocates memory for the class on the heap, and calls the constructor.
context switches do not have to occur.
The c++-runtime allocates the memory on its freestore using whatever mechanism it deems fit.
Usually the c++ runtime allocates large blocks of memory using OS memory management functions, and then subdivides those up using its own heap implementation. The microsoft c++ runtime mostly uses the Win32 heap functions which are implemented in usermode, and divide up OS memory allocated using the virtual memory apis. There are thus no context switches until and unless its current allocation of virtual memory is needed and it needs to go to the OS to allocate more.
There is a theoretical problem when allocating memory that there is no upper bound on how long a heap traversal might take to find a free block. Practically tho, heap allocations are usually fast.
With the exception of threaded applications. Because most c++ runtimes share a single heap between multiple threads, access to the heap needs to be serialized. This can severly degrade the performance of certain classes of applications that rely on multiple threads being able to new and delete many objects.
If you new or delete an address it's marked as occupied or unassigned. The implementations do not talk all the time with the kernel. Bigger chucks of memory are reserved and divided in smaller chucks in user space within your application.
Because new and delete are re-entrant (or thread-safe depending on the implementation) a context switch may occur but your implementation is thread-safe anyway while using the default new and delete.
In C++ you are able to overwrite the new and delete operator, e.g. to place your memory management:
#include <cstdlib> //declarations of malloc and free
#include <new>
#include <iostream>
using namespace std;
class C {
public:
C();
void* operator new (size_t size); //implicitly declared as a static member function
void operator delete (void *p); //implicitly declared as a static member function
};
void* C::operator new (size_t size) throw (const char *){
void * p = malloc(size);
if (p == 0) throw "allocation failure"; //instead of std::bad_alloc
return p;
}
void C::operator delete (void *p){
C* pc = static_cast<C*>(p);
free(p);
}
int main() {
C *p = new C; // calls C::new
delete p; // calls C::delete
}
Do you know if there is a way to bring back malloc in its initial state, as if the program was just starting ?
reason : I am developing an embedded application with the nintendods devkitpro and I would like to be able to improve debugging support in case of software faults. I can already catch most errors and e.g. return to the console menu, but this fails to work when catching std::bad_alloc.
I suspect that the code I use for "soft reboot" involves malloc() itself at some point I cannot control, so I'd like to "forget everything about the running app and get a fresh start".
There is no way of doing this portably, though concievably an embedded implementation of C++ might supply it as an extension. You should instead look at writing your own allocation system, using memory pools, or use an existing library.
Only time I did something similar, we used our own allocator which would keep a reference to each allocated blocks. If we wanted to rollback, we would free all the allocated blocks and do a longjmp to restart the programme.
Squirrel away a bit of memory in a global location e.g.
int* not_used = new i[1024];
Then when you get a std::bad_alloc, delete not_used and move on to your error console. The idea is to give your crash handler just enough space to do what you need. You'll have to tune how much memory is reserved so that your console doesn't also received out of memory errors.
If you're clever, not_used could actually be used. But you'd have to be careful that whatever was using memory could be deleted without notice.
The only way to get a fresh start is to reload the application from storage. The DS loads everything into RAM which means that the data section is modified in place.
I suppose if nothing else is running you could zero-write the whole memory block that the API provides on the Nintendo? But otherwise just keep track of your allocates.
In fact, if you create a CatchAndRelease class to keep a reference to each and every allocated memory block, at the required time you could go back and clear those out.
Otherwise, you may need to write your own memory pool, as mentioned by Neil.
Do you ever need to free memory in anything other than last-in-first-out order? If not, I'd suggest that you define an array to use all available memory (you'll probably have to tweak the linker files to do this) and then initialize a pointer to the start of that array. Then write your own malloc() function:
char *allocation_ptr = big_array;
void *malloc(size_t n)
{
void *temp = (void*)allocation_ptr;
if (allocation_ptr > END_OF_ALLOCATION_AREA - n)
return 0;
allocation_ptr += n;
return temp;
}
void free_all_after(void *ptr)
{
if (ptr)
allocation_ptr = (char*)ptr;
}
In this implementation, free_all_after() will free the indicated pointer and everything allocated after it. Note that unlike other implementations of malloc(), this one has zero overhead. The LIFO allocation is very limiting, but for many embedded systems it would be entirely adequate.
std::bad_alloc occurs when new fails and cannot allocate the memory requested. This will normally occur when the heap has run out of memory and therefore cannot honour the request. For this reason, you will not be able to allocate any new memory reliably in the cleanup.
This means that you may not allocate new memory for cleanup. Your only hope of cleaning up successfully is to ensure that memory for the cleanup code is pre-allocated well before you actually need it.
Objects can still be newed into this cleanup memory using the inplace new operator (ie new where you supply a memory address)