I have a c++ code. But it is not releasing memory properly. Tell me where I am wrong, here is my code
1 void MyClass::MyFunction(void)
2 {
3 for (int i=0; i<count; i++)
4 {
5 _bstr_t xml = GetXML(i);
6 // some work
7 SysFreeString(xml);
8 }
9 }
GetXML (line 5) returns me a BSTR. At this memory of program increases. But after SysFreeString (line 7) memory does not release. What I am doing wrong here?
First:
// This makes a copy.
// This is where the leak is. You are leaking the original string.
_bstr_t xml = GetXML();
// You want to use this, to attach the BSTR to the _bstr_t
_bstr_t xml = _bstr_t(GetXML(), false);
Second, don't do this:
SysFreeString(xml);
The _bstr_t class will do that for you.
Third, BSTR will not release the memory to the OS immediately, it caches recently used strings in order to make SysAllocString faster. You shouldn't expect to see memory usage go straight down after SysFreeString.
You can control this behaviour for debugging purposes:
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q139071
Lastly, when viewing memory usage in Task Manager you need to look at the column "Commit Size" not "Working Set". Go to Menu->View->Select Columns to show the column. And also note that this really only helps over a period of time - the memory may not be released to the OS immediately, but if you have no leaks, it shouln't go up forever, over a course of hours.
I suppose you should use :
xml.Attach(GetXML(i));
operator= looks like it is actually assigning new value - which means copying it. That value returned by GetXML stays unfreed.
also there should be no need for SysFreeString(xml);
Task Manager only provides the amount of memory allocated to the process. When C++ releases memory ( C's free) it does not necessarily return the memory to the Operating system so Task Manager will not necessarily show memory going doem until the process ends.
What Task Manager can show is if you keep allocating memory and not releasing it then the memory size of the process will keep increasing, if this happens you probably hava a memory leak.
When programming you need to use memory profilers to see if you are releasing memory. In Windows I used Rational's Purify to give me this information but it costs a lot. MS C runtime can be used to track memory. MSDN provides an overview here, read and follow th links.
As to your code and as per other comments and answers one of the points of using _bstr_t class is to do the memory and other resource management for you so you should not call SysFreeString
The destructor of _bstr_t will call SysFreeString(xml), so you don't need to call SysFreeString(xml) again. An additional memory free will result in crash.
Related
Currently I have a solution but I am not sure if it's alright in every scenario. Can I check if there is any memory leaks in the program with this solution? If anyone can offer a better solution please do not hesitate to share the answer. Thanks!
My example code here:
int *array = new int[5];
delete[] array; //so no memory leaks
//Memory leak check.
if (_CrtDumpMemoryLeaks()) {
std::cout << "Memory leaks!\n";
}
else {
std::cout << "No leaks\n";
}
cin.get();
return 0;
I found an other solution - Can someone agree with it? (source: https://learn.microsoft.com/en-us/visualstudio/profiling/memory-usage?view=vs-2017 )
1st step - create 3 breakpoints. !!! The last breakpoint should have put after the return - not in line!
2nd step - Start debugging and creating snapshots. (Diagnostic Tool)
3rd step - Click on the second snapshot and see 3 variables allocated dynamically in the heap.
4th step - Click on the third snapshot that we made - so we took it after releasing memory of the 'a' pointer with: delete a; That's why the size here is only 8 bytes. (12 bytes - 4 bytes that we have just released)
In your case, the best suited thing would be as you used in the first place, the CRT library and indeed the use of _CrtDumpMemoryLeaks(); as Microsoft documentation says:
The _CrtDumpMemoryLeaks function determines whether a memory leak has occurred since the start of program execution.
Concerning your other doubt:
but I am not sure if it's alright in every scenario
Per the microsoft documentation, it should log any memory leak occuring in your whole program even if it is in a class or anywhere where you might think as it:
Dumps all the memory blocks in the debug heap when a memory leak has occurred
Also don't forget to #define the _DEBUG flag as mentionned here:
When _DEBUG is not defined, calls to _CrtDumpMemoryLeaks are removed during preprocessing.
but nevertheless if you're making software you should use STL and use smart pointers.
Also you might have another way of checking a memory leak for a certain resource at a time, I use the memory tab provided by visual studio when debugging which is located in debug > windows > memory > memory1 (Note: you'll have to be in debug mode to see the setting) then in the search bar you can type array so you go where your pointed to memory lives, and then you could just step into your program and see if the memory is nulled out or not.
Note:
This is more if you want to visually monitor one resource at a time and not if you want a whole dump of each possibly leaked resources.
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.
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.
I have an application running on an ARM Cortex-A9. When I enter a certain portion of the code, I can see in the Linux tasks view 'top' that the application grows in memory usage until it gets Killed due to running out of physical memory.
Now, I have done some research on this and tried to implement mtrace, but it didn't give me very concise results. Basically I get something like this
Memory not freed:
-----------------
Address Size Caller
0x03aafe18 0x38 at 0x76e73c18
0x53a004a8 0x38 at 0x76e73c18
And I do not even think this is the big problem (maybe another smaller issue).
I also cannot use Valgrind (which would probably work great) because there is not enough space on the device to install it and a compiler...
So I fear that I just have to go through the code and look for something that could be causing growing memory usage. Is there a guide for this somewhere? In the code, "malloc" or "new" is almost never used.
I do have access to use gdb, if that can help.
One thing I am not clear on is if the following is a problem:
while(someloop){
...
double *someptr;
...
}
or like
while(someloop){
...
int32 someArray[100] = {0};
...
}
Of which there is a lot of in the code. When that loop comes around, and instantiates those variables or pointers, does it just keep using free space, or use the spaces from the last iteration?
If it is alocated on the stack, the memory is reused. However by alocating on heap you need to delete.
Also if you alocate with double * ptr; ... ptr = new double [5], you need to delete by delete [] ptr.
In C++ you can overwrite the new and delete operators to print some message for debuging.
Best would be to debug using gdb and see what object is created and not deleted.
It is possible that you use a class in your code that does not delete something internal.
Tip: for small objects alocating on stack is both faster and safer.
I'm allocating memory using new as and when I receive data in one of my methods and in the destructor, I'm releasing all the allocated memory using delete.
However, after releasing the memory, from the task manager, when I look at mem usage under the process tab, the memory usage still remains the same. It doesn't give an impression that the memory is being released.
So, when does the memory actually get released? And what is the best way to find out the actual memory being used by a process.
Thanks
In most cases, it's never given back to the OS while the app is running. Afterwards, of course, all resources are recovered by the OS.
[Edited after the comments rightly pointed out that 'never' is a long time ...]
The OS allocates a default heap to your application. This heap is allocated during the initialization of your process. Thus, your new's and delete's won't affect the bar you see in the task manager.
However, if you try to initialize a big buffer and the allocated heap isn't enough, the OS will allocate more memory for your application - and this should be reflected in the task manager...