Look at the following C++ code:
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
class Buf
{
public:
Buf(size_t size)
{
_storage.reserve(size);
}
~Buf()
{
vector<int> temp;
_storage.swap( temp );//release memory
}
vector<int> _storage;
};
int main()
{
int i = 0;
while( ++i < 10000)
{
Buf *buf = new Buf(100000);
delete buf;
}
return 0;
}
I run it in debug mode(VS2008):when I set a break point in the line
//main function
int i = 0;
I find that the Process MyProgram.exe occupies about 300KB memory in Windows Task Manager.When I set a break point in the line
return 0;
The Process MyProgram.exe occupies about 700KB in Windows Task Manager.
My question is :why the memory that the program occupies increased?I think I have release the memory exactly~Why?
Standard memory allocator will not (usually) release memory to OS when you deallocate it. Instead it will keep it for subsequent allocations for your process.
Thus you don't see memory ussage decrease in TM even though you deallocated it.
The OS/Debug environment might employ optimization techniques and your memory releasing probably just returns it to pool; the actual memory release probably occurs on program termination
Related
I have a c++ program and I want to tracking the heap memory when running
int MyFunction(){
//do function logic here
//do function logic here
.....................
//Check memory state in heap at the end of function
_CrtMemState crtMemState;
_CrtMemCheckpoint(&crtMemState);
printf("Memory: %d\n",crtMemState.lTotalCount);
}
int main(){
while(true){//Yes infinitive for long run test
MyFunction();
}
}
I got the result of memory :
Memory: 47435440
Memory: 76571670
Memory: 105710436
Memory: 135412510
Memory: 164726468
Memory: 194256398
Memory: 223569972
......
It's mean that the memory is increase for each function execution.
Does this mean MyFunction() has leak?
I tried some method like visual leak detector or _CRT* relate function but have no report about leak. My program running with memory increase by time ( I used PerfMonitor to check)
It doesn't mean it leaks
If we look at this code :
#include <iostream>
#include <vector>
int MyFunction(){
// no leak
static std::vector<int> v;
v.push_back(1);
std::cout << "memory used : " << v.size() * sizeof(int) << std::endl;
}
int main(){
while(true){//Yes infinitive for long run test
MyFunction();
}
}
this will produce :
memory used : 40140
memory used : 40144
memory used : 40148
File size limit exceeded
The vector will, at some time, ask for more memory than the PC can give, and the program will crash.
So if your MyFunction will be called an huge number of time, your program will crash too.
But it's not always a leak. May be, May be not.
In my code there is no leak, and the vector will be destroy after the main (well no because of the while(1) but we know how to clean the memory).
A leak is a memory we can't destroy anymore because we "lost" where it is. Like this :
int MyFunction(){
// leak
new int();
}
Here we can't call delete on this int because its address is long lost.
You may read the paragraph about Syntactic vs Semantic Memory Leaks here.
I am taking a class on c++ for which I need to write a simple program that leaks memory on purpose. I have tried this by creating new char [] and not deleting them, but this does not seem to work. Below is the complete code I have tried.
#include <iostream>
#include <cstring>
int main()
{
int i=1;
while (i<1000){
char *data = new char [100000000];
*data = 15;
i++;
}
}
When I watch the memory usage of the program it does not grow so it is not leaking any memory. I just get a bad allocation error.
I think the simplest case of memory leakage is dynamically creating an object then immediately losing the reference to it. In this short example, you are immediately losing a reference to the variable you've created, causing the memory leak. Memory leaks in small, contrived programs like these make it hard to appreciate memory leaks because as soon as a program exits, the operating system reclaims the memory the program allocated.
The problem becomes serious when the program runs for long periods of time. The memory leak is exacerbated and computer performance is noticeable hampered.
Example:
#include <iostream>
// Object is being created, allocated on the heap then function immediately exits, losing any reference to the object. This is a memory leak
void createObject()
{
int* x = new int;
}
int prompt()
{
int response;
std::cout << "Run again?\n";
std::cin >> response;
return response;
}
int main()
{
while(continue)
{
createObject();
// Running the program again and again will exacerbate the memory leak.
continue = prompt();
}
return 0;
}
Correct way to retain object reference in this contrived and useless example:
int* createObject()
{
int* x = new int;
return x;
}
int main()
{
// Pointer to the object created in the function in this scope is created, so we still have access to the variable.
int* a = createObject();
return 0;
}
Hope this helps, good luck in your class!
If you put some delay in the loop, you will be able to see the memory grow.
You can use sleep or wait for input from the user.
As it is now, the memory inflate so fast till you run out of allocation memory.
This is not a classic test of memory leak.
Memory leak it tested at the end of the program to see if you released all the memory.
#include <iostream>
#include <string>
#include <deque>
#include <vector>
#include <unistd.h>
using namespace std;
struct Node
{
string str;
vector<string> vec;
Node(){};
~Node(){};
};
int main ()
{
deque<Node> deq;
for(int i = 0; i < 100; ++i)
{
Node tmp;
tmp.vec.resize(100000);
deq.push_back(tmp);
}
while(!deq.empty())
{
deq.pop_front();
}
{
deque<Node>().swap(deq);
}
cout<<"releas\n";
sleep(80000000);
return 0;
}
By top ,I found my program's memory was about 61M, why? And it's ok if there is a copy-constructor in Node.I would like to know why , not how to make it correct.
gcc (GCC) 4.9.1, centos
Generally, new/delete and malloc/realloc/free arrange for more memory from the OS using sbrk() or OS-specific-equivalent, and divide the pages up however they like to satisfy the program's allocation requests. It's not worth the bother to try to release small pages back to the OS - too much extra overhead tracking the pages that are / are not still part of the pool, rerequesting them etc.. In low memory situations, normal caching mechanisms will allow long-unused memory pages to be swapped out of physical RAM anyway.
FWIW, GNU libC's malloc et al. makes an exception for particularly large requests so they can be fully released for the OS / other programs to use before program termination; quoting from the NOTES section here:
When allocating blocks of memory larger than MMAP_THRESHOLD bytes, the glibc malloc()
implementation allocates the memory as a private anonymous mapping
using mmap(2). MMAP_THRESHOLD is 128 kB by default, but is
adjustable using mallopt(3). Allocations performed using mmap(2) are
unaffected by the RLIMIT_DATA resource limit (see getrlimit(2)).
If container is vector, you can use swap to release memory, container is deque, you should use clear to release memory, like this:
int main ()
{
deque<Node> deq;
for(int i = 0; i < 100; ++i)
{
Node tmp;
tmp.vec.resize(100000);
deq.push_back(tmp);
}
while(!deq.empty())
{
deq.pop_front();
}
deq.clear();
// Or, you should try to use `deque<Node>().swap(deq);`, not `local`.
cout<<"releas\n";
sleep(80000000);
return 0;
}
I have some question about the delete[] p. I've written some code snippet for test this function. But I found that after executing the delete[] p, only the first 2 array elements were deallocated while the remaining not. Please see my test snippet and the output result as below. Who can tell me why and how can I clear off the whole memory for the unused array? Thanks!
#include <iostream>
using namespace std;
int main()
{
int *p;
p = new int[20];
for(int i=0;i<20;i++)
{
p[i]=i+1;
}
cout<<"------------------------Before delete-------------------------"<<endl;
for(int i=0;i<20;i++)
{
cout<<"p+"<<i<<":"<<p+i<<endl;
cout<<"p["<<i<<"]:"<<p[i]<<endl;
}
delete[] p;
cout<<"-------------------After delete------------------------"<<endl;
for(int i=0;i<20;i++)
{
cout<<"p+"<<i<<":"<<p+i<<endl;
cout<<"p["<<i<<"]:"<<p[i]<<endl;
}
return 0;
}
OUTPUT IN www.compileronline.com
Compiling the source code....
$g++ main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
------------------------Before delete-------------------------
p+0:0xa90010
p[0]:1
p+1:0xa90014
p[1]:2
p+2:0xa90018
p[2]:3
p+3:0xa9001c
p[3]:4
p+4:0xa90020
p[4]:5
p+5:0xa90024
p[5]:6
p+6:0xa90028
p[6]:7
p+7:0xa9002c
p[7]:8
p+8:0xa90030
p[8]:9
p+9:0xa90034
p[9]:10
p+10:0xa90038
p[10]:11
p+11:0xa9003c
p[11]:12
p+12:0xa90040
p[12]:13
p+13:0xa90044
p[13]:14
p+14:0xa90048
p[14]:15
p+15:0xa9004c
p[15]:16
p+16:0xa90050
p[16]:17
p+17:0xa90054
p[17]:18
p+18:0xa90058
p[18]:19
p+19:0xa9005c
p[19]:20
-------------------After delete------------------------
p+0:0xa90010
p[0]:0
p+1:0xa90014
p[1]:0
p+2:0xa90018
p[2]:3
p+3:0xa9001c
p[3]:4
p+4:0xa90020
p[4]:5
p+5:0xa90024
p[5]:6
p+6:0xa90028
p[6]:7
p+7:0xa9002c
p[7]:8
p+8:0xa90030
p[8]:9
p+9:0xa90034
p[9]:10
p+10:0xa90038
p[10]:11
p+11:0xa9003c
p[11]:12
p+12:0xa90040
p[12]:13
p+13:0xa90044
p[13]:14
p+14:0xa90048
p[14]:15
p+15:0xa9004c
p[15]:16
p+16:0xa90050
p[16]:17
p+17:0xa90054
p[17]:18
p+18:0xa90058
p[18]:19
p+19:0xa9005c
p[19]:20
The memory is cleared - there's just no requirement that the compiler will actually zero out an int in its destructor. What you're seeing is that the compiler didn't think that was necessary, so it's still there. The destructor is called though and the memory is freed.
You can see that more clearly if you did something like:
struct A {
int i;
A() : i(7) { }
~A() {
std::cout << "deleting A." << std::endl;
i = 0;
}
};
And repeat your experiment with A* p = new A[20];.
It is important to distinguis between cleared memory and deleted memory.
When memory is cleared it is initialized to some value - perhaps all zeros. But when memory is deleted or freed, it is returned to the heap. When the memory is released the memory manager is under no obligation to clear the memory. The two bytes you see being changed are likely from a debug marker used by the memory manager to help track buffer overruns.
If you want to clear all of the memory, you need to do it before you delete it - only at that point do you still have ownership of that memory. Clearing it after deleting it is operating on memory you do not own.
Following program creates Objects in one loop and store the reference in vector for future deletion.
I am seeing an unusual behavior, even though the objects are deleting in the second iteration, the getrusage gives a resident memory higher compared to object creation.
Execution environment is in Linux Kernel 3.2.0-49-generic.
#include <iostream>
#include <vector>
#include <stdio.h>
#include <mcheck.h>
#include <sys/time.h>
#include <sys/resource.h>
using namespace std;
void printUsage(string tag)
{
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
printf("%s -- Max RSS - %ld\n", tag.c_str() ,usage.ru_maxrss);
}
class MyObject
{
public:
char array[1024 * 1024];
MyObject() {};
~MyObject() {};
};
int main()
{
printUsage("Starting");
vector<MyObject *> *v = new vector<MyObject *>();
for(int i = 0; i < 10000; i++)
{
MyObject * h = new MyObject();
v->push_back(h);
// The max resident value is same. usual behavior.
// delete h;
}
printUsage("After Object creation");
for(size_t i = 0; i < v->size(); i++)
{
MyObject * h = v->at(i);
delete h;
}
v->clear();
delete v;
printUsage("After Object deletion");
return 0;
}
g++ test/test.cpp -Wall -O2 -g
Output
Starting -- Max RSS - 3060
After Object creation -- Max RSS - 41192
**After Object deletion -- Max RSS - 41380**
I'm not up on the specifics of getrusage but from a quick google, it seems to be reports OS resources used. Typically, the C++ Run-time library which manages the memory used by malloc/new will request a large block of memory from the OS when it needs it, make malloc requests out of that block, and then hold onto the block even after all the allocations are freed, so it has some avaiable to handle the next request without having to ask the OS again.