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.
Related
I'm attempting to implement my own array using pointers in C++. I'm using Visual Studio. I'm relatively new to C++, so if there is something obvious that I'm missing bear with me. But when I run it the first time, it works as intended. However, the next time I run it, I get one of two errors. One of the errors is
Unable To Start Program, Access Denied.
"the path of the file"
Access Is Denied
The other one that comes up rarely is
main.cpp has triggered a breakpoint
I think it has something to do with a wrong use of pointers, however that doesn't explain why it works the first time. Here is the code:
In main.cpp:
#include <iostream>
#include <vector>
#include "linked_list.hpp"
#include "trie.hpp"
#include "stack.hpp"
#include "queue.hpp"
#include "array.hpp"
int main() {
data_structures::array arr(5);
arr.set(4, 1);
int fourth_index = arr.get(4);
std::cout << fourth_index;
}
In array.hpp:
#pragma once
namespace data_structures {
class array {
private:
int* start;
public:
array(int size) {
start = new int(0);
for (int i = 1; i < size; i++) {
*(start + i) = 0;
}
}
public:
void set(int index, int val) {
if (index == 0) {
start = new int(val);
} else {
*(start + index) = val;
}
}
int get(int index) {
return *(start + index);
}
};
}
The first time, I get the correct output:
1
Then the next time I get the error I stated above.
Try changing this line:
start = new int(0);
to:
start = new int[size];
new int(0) is initializing "start" as a pointer to just one int with a value of 0. Instead, you need to allocate the memory necessary to hold your array. I suspect you're running into issues because you're writing into memory that you haven't allocated yet.
As a side note, make sure to add a destructor and free your memory.
Well you must be right! It is a memory issue and the error message "main.cpp has triggered a breakpoint" on windows indicates corruption of the heap in this case! I didn't have access to the hpp files you used apart from array.hpp
Let's start with some memory issues that your code is making
While initializing your array you are only initializing a single integer. But you need multiple integers in the array when you say want an array of size 5, you need to declare 5 integers. So you should declare an entire memory space for that. I am using malloc for this.
int* start = (int *)malloc(size*sizeof(int))
Secondly in your code for set there is a logical error that would change your start pointer from the original array which should not be happening. Instead you should just change the value at start.
*start = val;
#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.
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
I should probably be sleeping. Instead, I'm coding. Specifically, I've written The World's Worse Memory Allocator(TM). It's got an array of bytes (chars) to use for memory for stuff; it's got a list of used memory blocks; it's got an index to allocate memory from. It even allocates memory. Deallocates, not so much.
That shouldn't be a problem, though, as to the best of my knowledge, nothing is new'd outside of the array and list classes and the destructor for those is called the proper number of times.
Edit: The problem is, the program enters what appears to be an infinite loop somewhere in the c++ back-end code itself, shortly after the MemoryManager's destructor is called. In fact, if the MemoryManager is put inside the Try-Catch block, the program never makes it outside the Try-Catch block. I need to know why and how to fix it, please, thanks.
This is the main loop which is doing terribly important allocations:
int _tmain(int argc, _TCHAR* argv[])
{
MemoryManager memoryManager = MemoryManager(1024);
try
{
int * n;
for (int t = 0; t < 32; ++t)
{
n = (int*)memoryManager.Allocate(4);
}
} catch (char* str) { std::cout << str; }
return 0;
}
And the MemoryManager, in all it's newbie glory:
// A memory manager
#pragma once
#include "stdafx.h"
#include "Array.h"
#include "SmartPointer.h"
class MemBlock
{
public:
unsigned int Start;
unsigned int End;
MemBlock() { Start = 0; End = 0; }
MemBlock(unsigned int start, unsigned int end)
{
Start = start; End = end;
}
~MemBlock() { }
};
class MemoryManager
{
private:
Array<char> memory;
List<MemBlock> memBlocks;
int index;
public:
MemoryManager(unsigned int size)
{
memory = Array<char>(size);
memBlocks = List<MemBlock>(size / 24);
index = 0;
}
~MemoryManager() { }
void* Allocate(unsigned int size)
{
memBlocks.Add(&MemBlock(index, index + size));
void* r = (void*)(memory.insecureAccess + index);
index += size;
return r;
}
};
Thanks.
You don't seem to have asked a question here, but I'm going to point out a horrible flaw in your approach anyway :)
If you are planning to write a Deallocate(void*) method then you are going to struggle.
You can match the void* pointer against your memBlocks list to determine which MemBlock it is, but you will only be able to reduce index if that MemBlock happens to be the last one returned by Allocate otherwise it is just a free hole in your array.
For a basic solution to this you would need a list of the free blocks and you would take allocated blocks from that list, and add them back to the list when they were deallocated.
This approach is called a free list: http://en.wikipedia.org/wiki/Free_list
Solved - Error in ignorance; it was an indirect error. I was using "delete theArray;" in the Array destructor (Array also being the base class of List) when I should have been using "delete [] theArray". The pause is now gone and the problem seems solved. Thanks for your time.