STL not release memory from System level - c++

As I know STL has automatic memory management. But when I use something like top or ps -aux to show the memory usage of a process, it shows even the STL object are out of scope, these memory is still possessed by process.
Here is an example:
void run()
{
map<int, int> a;
for(int i = 0; i < 1000000; i++)
{
a[i] = i;
} // 64376K memory used by process
}
int main()
{
run();
sleep(5); // still 64376 memory used
map<int, int> a;
for(int i = 0; i < 1000000; i++)
{
a[i] = i;
} // still 64376 memory used
return 0;
}
The process possesses 64376KB memory in run() and memory doesn't release after function run(). But these memory seems to be used by the second map.
After I use valgrind --tool=massif to check what happened, I got a normal result.
So here comes my question
why process memory trends doesn't match with the code and valgrind
How does the different STL objects share the same allocated memory.

This is completely normal. That's how operating systems work. If they spent all their time reclaiming tiny portions of memory from tiny processes, they'd never do anything else.
You just have to trust that their complicated algorithms know what they're doing to get the best performance for your system.
There are layers on layers on layers of logic that allocate physical RAM all the way up to the process's virtual memory.
Going into extreme detail about how operating systems work would be both beyond the scope of this post, and pointless. However, you could enrol on a relevant teaching course if you really wanted to grok it all.
If we were to forget about caching and virtual memory and such, even a simple rule of thumb might be summarised as follows: releasing memory from your program tells the OS it can have it back; that doesn't mean the OS must take it back.

Related

Is it okay to parallelize memory allocation delete with openmp? (c++)

int **something = new int *[N];
for(int n = 0; n < N; n++)
something[n] = new int[M];
#pragma omp parallel for
for (int n = 0; n < N; n++)
delete[] something[n];
delete[] something;
Can I parallelize a delete process like this?
OOM killer of Linux killed my process after quite big number of loops. I tried to figure out where the memory is leaking, but I could not find where. I am not sure if these for loop delete process worked well or not.
This is generally okay. The standard (g)libc heap must be thread-safe; otherwise, it'd be impossible to write threaded programs at all. It's also fine to allocate a buffer on one thread and free it on another.
Parallelizing heap allocations won't give you much of a speed-up, but I suspect you're asking not because you want to speed up (de-)allocation, but rather because you have some other parallel code that happens to allocate and free some buffers.
To find your leak, try running your program with valgrind.
Additionally, consider calling malloc_trim(0); after freeing large amounts of memory. This makes glibc release unused memory back to the operating system, instead of holding onto all of it for later allocations.

Understanding C++ map why heap memory isn't released with clear()?

Suppose I have a forever loop to create hashmap:
void createMap() {
map<int, int> mymap;
for (int i = 0; i < INT_MAX; i++) {
mymap[i] = i;
}
mymap.clear(); // <-- this line doesn't seem to make a difference in memory growth
}
int main (void) {
while (1) {
createMap();
}
return 0;
}
I watched the code run and on MacOS, watching the Activity Monitor, the application keeps growing the memory usage with or without the mymap.clear() at end of the createMap() function.
Shouldn't memory usage be constant for the case where mymap.clear() is used?
What's the general recommendation for using STL data containers? Need to .clear() before end of function?
I asked in another forum, the folks there helped me understand the answer. It turns out, I didn't wait long enough to exit createMap function nor do I have enough memory to sustain this program.
It takes INT_MAX=2147483647 elements to be created, and for each map = 24 bytes element of pair<int, int> = 8 bytes.
Total minimum memory = 2.147483647^9 * 8 + 24 = 17179869200 bytes ~= 17.2 GB.
I reduced the size of the elements and tested both with and without .clear() the program grew and reduce in size accordingly.
The container you create is bound to the scope of your function. If the function returns, its lifetime ends. And as std::map owns its data, the memory it allocates is freed upon destruction.
Your code hence constantly allocates and frees the same amount of memory. Memory consumption is hence constant, although the exact memory locations will probably differ. This also means that you should not manually call clear at the end of this function. Use clear when you want to empty a container that you intend to continue using afterwards.
As a side note, std::map is not a hash map (std::unordered_map is one).

C++ bad_alloc error after running code successfully multiple times

I am relatively new to C++ and I've having an issue with my project.
I ran the following code a few times without a problem, but now when I try to run it it gives me a std::bad_alloc error. The code is C++ but some lines are exclusive to ROOT which is program written in C++ for particle physicists.
class Particle {
public:
int pdgid;
float px;
Particle(int pdg, float px){
pdgid = pdg;
px = px;
}
};
TFile* file = new TFile("filename.root"); //ROOT code, where particle values are obtained from.
TTree* tree = (TTree*)file->Get("FlatTree"); //tree is where all events and associated values are held
vector<Particle> allparticles;
for (unsigned iEntry = 0; iEntry<tree->GetEntries(); iEntry++) {
tree->GetEntry(iEntry);
for (int iVecEntry = 0; iVecEntry < nfsp; iVecEntry++) {
allparticles.push_back(Particle(pdg[iVecEntry],px[iVecEntry]));
}
}
The code works if I decrease the limit of the first for loop. The number of entries is quite large (over 2 million) and nfsp can be up to 24 depending on the event. This resulted in the vector allparticles having over 7 million Particle objects.
I think the problem lies with not having enough memory to allocate such a large vector but how was this working previously? Is it possible that the memory wasn't deallocated properly the first few times I ran the code?
I a bit confused about memory management. In C++ does the OS handle deallocation? Or do I have to include a destructor?
I have tried including a destructor but could not get it to work.
From "std::bad_alloc": am I using too much memory? I tried including a delete[] statement at the end of the code but this also doesn't work.
Any input and help is much appreciated!
P.S. I'm running linux mint 18.2 Sonya.
Yes, it sounds like you have run out of stack memory. Here is one of the many tutorials out there that explain heap vs stack memory.
You are creating your particles in stack memory, so this means that they will be automatically destroyed when they go out of scope. You stack memory size varies depending on the compiler and environment, but you get way less stack memory than heap memory.
To fix this, I would create a vector of pointers to Particles, and create the Particles dynamically. Example:
vector<Particle*> allparticles;
...
allparticles.push_back(new Particle(pdg[iVecEntry],px[iVecEntry]));
Remember, to delete the dynamically allocated heap memory when you are done with it. Example:
for(int i < 0; i < allparticles.size(); i++){
delete allparticles[i];
}

Clear vector of vectors effectively C++

I came across having the need to create 2 or 3-level nested vectors but I had this issue of memory not clearing correctly. So I made this simple test:
void test(){
vector<vector<double>> myContainer;
vector<double> vec = {1};
for (int i=0; i<20000000; ++i)
{
myContainer.push_back(vec);
}
FreeAll(myContainer);
}
where FreeAll() is a template function defined as follows:
template <typename T>
void FreeAll( T & t ) {
T tmp;
t.swap(tmp);
}
Now, invoking function test() in main(), we will find out that a lot of left over memory is still there even after leaving the test function's scope and that memory is not cleared up until the main terminates.
Could be the reason for this that I create too much vectors? also there is no any kind of memory leak here as all the storage is automatic.
In this very context, there is no any sort of memory leaks and memory observations occurred from Ubuntu's default system monitor.
So calling test() 4 times in main() and check if the last 3 calls would allocate more memory or reuse it from the previous allocation and it turns out that no more memory would be allocated and the memory is indeed reusable and it will be only freed once the program terminates. On the contrary, creating a vector of double and pushing the same number of doubles and call FreeAll(), it will actually free the memory instantly and it's returned to the OS.

Delete, Free, or Deallocate?

I'm running into a problem where I use too much memory on the stack. I'm using several large arrays that I only need between steps in my code. Basically I need to know how to release the memory used by an array variable that's created as:
float arrayName[length][width];
To intentionally release some auto storage (items on the 'stack'), you can do the following - basically you simply limit the scope of your variables
change code from:
//...
float arrayName[length][width];
// ...
change code to:
//...
{
float arrayName[length][width];
// use arrayName here
//... still in-scope
} // scope limit
// all of arrayName released from stack
{
// stack is available for other use, so try
uint32_t u32[3][length][width];
// use u32 here
//... still in-scope
} // scope ended
// all of u32 released from stack
// better yet, use std::vector or another container
std::vector<uint32_t> bigArry;
NOTE: a vector uses a finite amount of stack (24 bytes on my system),
regardless of how many elements you put into it!
You should use vectors for things like this. It is a part of the C++ standard library and is very optimized in most implementations. The memory taken up by the vector will automatically get released when the vector goes out of scope. So you will never have to free up the memory yourself.
Another benefit with using a vector is that you do not have to worry about running out of stack space since all the "array" memory taken up by the vector is located on the heap of the program.
For examples http://en.cppreference.com/w/cpp/container/vector/vector
Other than that if you think your program memory is never going to be enough then you should consider using the disk as another storage mechanism. Databases work this way. They store most of their data on disk.
You won't need any special statements.
The array will be released on function return or exiting the scope if it is local variable having automatic storage duration, or on exiting the program if it is static variable (declared outside functions).
You may want to allocate the memory on the heap if you are running into a situation where you are running out of memory on the stack. In this case you'll want to new up the array.
float** my_array = new float* [rowCount];
for(int i = 0; i < rowCount; ++i)
{
my_array[i] = new float[columnCount];
}
// and delete it later
for(int i = 0; i < rowCount; ++i)
{
delete [] my_array[i];
}
delete [] my_array;