strange C++Memory leak from 2D array - c++

I'm using xcode and instruments to find my memory leak, it is complaining that this following code creates memory leak:
double **cn2;
cn2= new double*[noOfItem];
for(int i=0;i<noOfItem;i++)
{
cn2[i]=new double[noOfItem];
}
for(int i=0;i<noOfItem;i++)
{
for(int j=0;j<noOfItem;j++)
{
cn2[i][j]=getCN2(noOfItem,i,j,pearson,cn2CutOff);
//cout<<i<<" "<<j<<" "<< cn[i][j]<<endl;
}
}
for(int i=0;i<noOfItem;i++)
{
delete [] cn2[i];
}
delete [] cn2;
This is the function of getCN2, it is used to fill the 2d array:
double getCN2(int _isize,int _i1,int _i2,double **sim,double _cutoff)
{
//cout<< med<<" "<<med1<<endl;
int count=0;
for(int i=0; i<_isize; i++)
{
//if(sim[_i1][i]>_cutoff && sim[_i2][i]>_cutoff)
if(sim[_i1][i]>sim[_i1][_i2] && sim[_i2][i]>sim[_i1][_i2] && sim[_i1][_i2]>0)
{
count++;
}
}
//cout << rez/sqrt(rez1*rez2) <<endl;
return count;
}
And there is no memory leak if I change my code into:
double **cn2= new double*[noOfItem];
for(int i=0;i<noOfItem;i++)
{
cn2[i]=new double[noOfItem];
}
for(int i=0;i<noOfItem;i++)
{
for(int j=0;j<noOfItem;j++)
{
cn2[i][j]=getCN2(noOfItem,i,j,pearson,cn2CutOff);
//cout<<i<<" "<<j<<" "<< cn[i][j]<<endl;
}
}
for(int i=0;i<noOfItem;i++)
{
delete [] cn2[i];
}
delete [] cn2;
The only possible reason I could think of is that when I call double **cn2; it points to something already and when I call cn2= new double*[noOfItem]; it points to something else and the original **cn2 didn’t get freed? Has anyone else encountered this problem before? It is really weird...Do I have to write them in one line instead of 2 when using new to allocate?

do preventing coding to avoid such kind of error
Pointer initialization is must
double *ptr = nullptr;
Check is required before allocating memory
if (nullptr==ptr) { ....}
If you writing new code then avoid usage of raw pointer
unique_ptr. Allows exactly one owner of the underlying pointer.
shared_ptr. Reference-counted smart pointer. ...
weak_ptr. Special-case smart pointer for use in conjunction with shared_ptr
Debugging technique:-
Use of visual studio to find memory related error
Buffer Overflow explained
Use diagnostic tool
Vld and parallel studio

Related

Why does my program return garbage when accessing the value of a pointer?

When the below code is run, I get garbage output. I have debugged it enough to figure out the error comes when I try to access hobbies[i]->hobby. Any help would be appreciated. I have been trying to figure out what is going on for hours.
int Graph::addUserToHobby(std::string hobby, std::string id){
int key = ((int)hobby[0] + (int)hobby[1])%HASHMAP_SIZE;
int collisions = 0;
while(hobbies[key] != NULL && hobbies[key]->hobby.compare(hobby) != 0 ){
key++;
collisions++;
if(key >= HASHMAP_SIZE){
key = 0;
}
}
if(hobbies[key] == NULL){
hobbylist hob;
hob.hobby = hobby;
hob.list.push_back(findVertex(id));
hobbies[key] = &hob;
}
else{
hobbies[key]->list.push_back(findVertex(id));
}
return collisions;
}
void Graph::displayHobbies(){
for(int i=0; i<HASHMAP_SIZE; i++){
if(hobbies[i] != NULL){
cout << hobbies[i]->hobby << ": ";
for(unsigned int j=0; j<hobbies[i]->list.size()-1; j++){
cout << hobbies[i]->list[j]->name << ", ";
}
cout << hobbies[i]->list[hobbies[i]->list.size()-1]->name << endl;
}
}
}
Focus your attention in that part of the code:
if(hobbies[key] == NULL) {
hobbylist hob;
...
hobbies[key] = &hob;
}
When hob gets out of scope (at the end of that if-statement's body), hobbies[key] will reference something that doesn't exist any more.
Later on in your program, as you correctly noticed, when you do cout << hobbies[i]->hobby;, you will request for hobby on something that has gone out of scope, which invokes Undefined Behavior (UB).
Some possible solutions:
Use an std::map, instead of the array of pointers you use
now. The container will automatically take care of the memory
management for you. (Recommended)
Use smart pointers (e.g. std::unique_ptr), instead of raw pointers. Read more in
What is a smart pointer and when should I use one?
Dynamically allocate hob, so that its lifetime is extended (that
means that when that if-statement's body terminates, hob's
lifetime won't terminate). This approach requires you to be
responsible for the memory management (you have to de-allocate every
piece of memory that you dynamically allocated before (call delete
as many times as you called new)).
In this part:
if(hobbies[key] == NULL){
hobbylist hob;
/* ... */
hobbies[key] = &hob;
}
hob is allocated on the stack and deleted after the if block. So the pointer you have in hobbies[key] is dangling. You can catch these sort of errors with valgrind.
Your issue is that you are populating your hobbies value with pointers to objects allocated on the stack.
These objects will have subsequently been destroyed. Perhaps you were meaning to allocate them on the heap with new?
hobbylist* hob = new hobbylist;
...
hobbies[key] = hob

How can I prevent these memory leaks?

I met huge problem with memory leaks and I don't know where to put that "delete" to get rid of them. Below is part of my code, and there is a full one: https://pastebin.com/Wtk83nuH.
string* startowa(int& rozmiar)
{
rozmiar = 5;
string* tablica = new string[rozmiar];
for (int i = 0; i < rozmiar; i++)
tablica[i] = "text";
return tablica;
}
string* plusx(string* tab, int& rozmiar)
{
string tekst = "something";
string* tablica_3 = new string[rozmiar];
tablica_3[rozmiar - 1] = tekst;
for (int i = 0; i<rozmiar - 1; i++)
tablica_3[i] = tab[i];
return tablica_3;
}
string* minusx(string* tab, int& rozmiar)
{
string* tablica_3 = new string[rozmiar];
for (int i = 0; i < rozmiar; i++)
tablica_3[i] = tab[i];
return tablica_3;
}
int main()
{
int wybor = 1, rozmiar = 1;
string *tablica = startowa(rozmiar);
while (wybor != 55) {
cin >> wybor;
if (wybor == 1) {
rozmiar++;
tablica = plusx(tablica, rozmiar);
}
if (wybor == 6) wybor = 55;
else {
rozmiar--;
tablica = minusx(tablica, rozmiar);
}
// there were other "ifs" but its just a part of the code
}
for (int i = 0; i < rozmiar; i++)
cout << tablica[i] << endl;
delete[] tablica;
cin >> wybor;
getchar();
return 0;
}
The memory leak is your least problem in that source code. In fact, you don't need heap allocations at all in your example.
Here are some fast improvements:
- use "std::string" instead of just string, I guess you are using "using namespace std"
- do not return a pointer to string, you can just declare a string and return it
- do not use a reference to an int as a function parameter if you are not returning it
- use const as much as you can
- replace "string *" with "const string&" if you are not returning it
- do not allocate string on heap (with new), instead declare it on stack
- use vectors
You can use this great site and Scott Meyers books for other C++ good practices.
To prevent memory leaks like that, avoid manual memory management. There are a lot of tools available to you.
For example, take your string array:
string* startowa(int& rozmiar) {
rozmiar = 5;
string* tablica = new string[rozmiar];
// ...
}
This should be replaced by std::vector. And since a vector keep track of it's size, you don't need to pass the size as reference:
std::vector<std::string> startowa() {
// ...
std::vector<std::string> tablica(5);
// ...
}
Then, your function that operates on the array should take the vector by reference to about copies, and return another vector. Since a vector already has a function that insert a new element, your plusx function becomes this:
void plusx(std::vector<std::string>& tab) {
std::string tekst = "something";
tab.emplace_back(std::move(tekst));
}
And your minusx function becomes that:
void minusx(std::vector<std::string>& tab) {
tab.pop_back();
}
By the way, with a vector, you can completely remove your startowa function by replacing the call in your main by this:
// Was `string *tablica = startowa(rozmiar);`
std::vector<std::string> tablica(5, "text");
Since std::vector manages it's memory itself, you don't need to delete it anywhere.
If you don't want to use vector, you can alway use std::unique_ptr<std::string[]>. The only difference in you code would be to send tablica.get() to your functions, and use std::make_unique<std::string[]>(rozmiar) instead of new std::string[rozmiar]
The correct answer is use std::vector. For example:
vector<string> startowa(int& rozmiar)
{
rozmiar = 5;
vector<string> tablica(rozmiar);
for (int i = 0; i < rozmiar; i++)
tablica[i] = "text";
return tablica;
}
Note the return by value. Don't fall into the trap of thinking you're saving processing time by returning by reference. That vector goes out of scope and is destroyed at the end of the function. With a returned reference the best you can hope for is the caller receiving a load of garbage and crashing before any damage can be done.
A decent compiler will eliminate the copying when you return the vector by value, and if the compiler decides that it cannot, std::move will take care of that.
vector also knows how big it is, eliminating the need for rozmiar.
Now... What went wrong? Let's look at the code
int main()
{
int wybor = 1, rozmiar = 1;
string * tablica = startowa(rozmiar);
startowa allocated an array of strings and stored a pointer to the array in tablica.
while (wybor != 55)
{
cin >> wybor;
if (wybor == 1)
{
rozmiar++;
tablica = plusx(tablica, rozmiar);
plusx allocated a new array of strings, a pointer to which has been returned and written over the pointer returned by startowa. startowa's array is now effectively lost, leaked, as it is next to impossible to find again to delete[].
We would need to delete[] tablica; before making the assignment. Clearly we can't do this before calling plusx as tablica is a parameter, so we need to store a temp.
string * temp = plusx(tablica, rozmiar);
delete[] tablica;
tablica = temp;
But what if something unexpected happens and an exception is thrown? The code never hits the delete[] and BOTH allocations are lost. vector handles all this for you.
And back to the code
}
if (wybor == 6)
wybor = 55;
else
{
rozmiar--;
tablica = minusx(tablica, rozmiar);
Same problem and solution as above.
}
// there were other "ifs" but its just a part of the code
}
for (int i = 0; i < rozmiar; i++)
cout << tablica[i] << endl;
delete[] tablica;
One of an in-determinant number of allocations is released here. The rest are lost.
cin >> wybor;
getchar();
return 0;
}

c++ double free or corruption (out) error

I am getting error of "Double free or corruption(out)" after I print my output. But this error is only coming for small inputs. For bigger inputs program doesn't throw that error. When I create the multidimensional arrays inside the main and delete them, I do not get the error. I have only posted the part of the code which is relevant to this issue here. Please kindly explain how to resolve the issue.
#include<iostream>
#include<vector>
using namespace std;
class Knapsack{
public:
int noItems, capacity, value, weight;
int *weightArray, *valueArray;
int **ValueMatrix, **BacktrackMatrix;
vector<int> itemsChosen;
~Knapsack();
void getInputs(); // reads in data
void findItems(); // calculates best value of items
void backTrack(int row, int col); // backtracks items selected
void print(); //prints out data
};
Knapsack::~Knapsack()
{
delete[] weightArray;
delete[] valueArray;
for(int i=1;i<=noItems;i++)
{
delete[] ValueMatrix[i];
}
delete[] ValueMatrix;
for(int i=1;i<=noItems;i++)
{
delete[] BacktrackMatrix[i];
}
delete[] BacktrackMatrix;
}
void Knapsack::getInputs()
{
cin>>noItems;
cin>>capacity;
weightArray=new int[noItems];
valueArray=new int[value];
for(int i=1;i<=noItems;i++)
{
cin>>value;
valueArray[i]=value;
}
for(int i=1;i<=noItems;i++)
{
cin>>weight;
weightArray[i]=weight;
}
ValueMatrix=new int*[noItems];
for(int i=1;i<=noItems;i++)
{
ValueMatrix[i]=new int[capacity+1];
}
BacktrackMatrix=new int*[noItems];
for(int i=1;i<=noItems;i++)
{
BacktrackMatrix[i]=new int[capacity+1];
}
}
int main()
{
Knapsack *knap=new Knapsack();
knap->getInputs();
knap->findItems();
knap->print();
delete knap;
return 0;
}
I believe the root of your issue is caused by the allocation of valueArray, and the fact that you are iterating out of bounds.
The line valueArray=new int[value]; initializes valueArray with an array of size value which is an uninitialized variable. Perhaps you meant to use noItems?
Also, as songyuanyao pointed out in the comments, your for loops look like for(int i=1;i<=noItems;i++) which starts the counter at 1 and finishes with the counter at noItems, which is erroneous. In a lot of languages, C++ included, arrays start at index 0 (meaning the first item is array[0], not array[1]) and the last item is one minus the size of the array (so the last item of an array with 5 elements is array[4]).
If you change your for loop to start at 0 and end one element before noItems you should be golden. That would be for(int i = 0; i < noItems; i++ )
What's probably happening with smaller allocations is the different chunks of memory are arranged sequentially in the same area of the memory heap, so when you overrun the buffer with data, you're smashing new's bookkeeping data.
When you have larger allocations, the new memory can't fit as cleanly into the free space of the heap, so the allocator ends up leaving some slack space between the allocations. Thus, a small overrun doesn't destroy heap information.

Crash when deleting a pointer

I have an assignment to create a PriorityQueue structure and I'm having trouble with this piece of code. When I compile it on my compilator everything's fine, but I tried submitting it to ideone and I get the following error:
"glibc detected *** ./prog: double free or corruption".
I was able to track the part that was giving me this error and I found out that what causes the crash is me trying to delete a pointer at the destructor of my class. The problem is that I don't know why I cant delete it. I don't know a lot about pointers but I thought that if I used new to allocate memory I had to delete it after using it and I think this is what I'm trying to do. Here is my code:
struct PriorityQueue
{
LinkedList queue; LinkNode *it,*node;
int sz;
PriorityQueue(){
sz=0;
queue.head=NULL;
queue.tail=NULL;
it = NULL;
node=NULL;
}
~PriorityQueue(){
if(node != NULL) //this is causing the error.
delete [] node;
if(it != NULL)
delete [] it;
}
int size(){
return sz;
}
void enqueue(int x){
node = new LinkNode(x,NULL,NULL);
if(sz==0){
queue.insert_head(x);
sz++;
}
else{
if(x <= queue.head->value ){
queue.insert_head(x);
sz++;
}
else if( x>= queue.tail->value ){
queue.insert_tail(x);
sz++;
}
else{
it = queue.head;
for(int k=0;k<sz;k++){
if( (x>= it->value) && (x <= it->next->value) ){
node->next= it->next;
node->previous = it;
it->next->previous = node;
it->next = node;
sz++;
break;
}
it=it->next;
}
}
}
}
int dequeue_min(){
int min = queue.remove_head();
sz--;
return min;
}
int dequeue_max(){
int max= queue.remove_tail();
sz--;
return max;
}
};
int main()
{
PriorityQueue pq;
pq.enqueue(4);
pq.enqueue(2);
pq.enqueue(7);
pq.enqueue(-6);
pq.enqueue(0);
cout << pq.dequeue_min() << endl; // debe imprimir -6
cout << pq.dequeue_min() << endl; // debe imprimir 0
pq.enqueue(3);
cout << pq.dequeue_min() << endl; // debe imprimir 2
cout << pq.dequeue_min() << endl; // debe imprimir 3
return 0;
}
Thanks.
it and node point to objects, not arrays.
You cannot use the array form of delete[] on them.
Using delete[] will try to remove a pointer whose object is an array of some sort. There is another type of delete, that allows for the deletion of pointers to single objects. (Hint: it's pretty intuitive)
You are deleting it and node using delete []. They are not arrays. You can only use delete [] syntax on arrays or arrays of your objects. Remember the rule of thumb to use the similar delete and new commands for the same data types. If you have allocated memory by new, delete by delete. If you have allocated memory by new [], delete it by deete [].
It seems that it and node not only point to objects rather than arrays, as Slaks pointed out, it seems they also potentially point to the same thing. As a side note, you don't need to check for null before calling delete[] p or delete p: If the pointer p is null, this expression will have no effect.
It is unrelated to your question but please also note that your priority queue as O(n) (with n being the size) complexity. Typically, when implementing a priority queue you want to get O(log(n)) complexity. The easiest strategy to implement such a priority queue is a d-heap which, conveniently, lives in an array and is actually easier to maintain than your linked list (I think, at least).

How to pass two-dimensional array of structures to function?

There is a two-dimensional array of structures, I am passing an array pointer to a function:
result.capabilities = (Capabilities **)malloc(sizeof(Capabilities *)*6);
for(int i=0;i<6;i++){
result.capabilities[i] = (Capabilities *)malloc(sizeof(Capabilities)*8);
}
init_capabilities(&result.capabilities);
Function call cause an error:
Unhandled exception at 0x003c10f9 in solution.exe: 0xC0000005: Access violation writing location 0xfdfdfdfd.
Here is my function:
void init_capabilities(Capabilities ***capabilities) {
for(int i=0;i<6;i++){
for(int j=0;j<8;j++){
printf("%d %d\n",i,j);
capabilities[i][j]->room_capabilities = new RoomCapability[rooms_count];
}
}
}
I thought that the dimension of the array capabilities - 6x8. It turned out that 1x6.
An hour headache because of this. Show you how to change the type of argument or how to refer to elements of my array, so that everything fell into place?
You are passing your pointer-to-pointer-to-Capabilities by pointer. That is why you have three asterisks instead of two.
Try this:
void init_capabilities(Capabilities ***capabilities) {
for(int i=0;i<6;i++){
for(int j=0;j<8;j++){
printf("%d %d\n",i,j);
// Note: extra dereference:
(*capabilities)[i][j].room_capabilities = new RoomCapability[rooms_count];
}
}
}
Or this:
result.capabilities = (Capabilities **)malloc(sizeof(Capabilities *)*6);
for(int i=0;i<6;i++){
result.capabilities[i] = (Capabilities *)malloc(sizeof(Capabilities)*8);
}
init_capabilities(result.capabilities); // Note NO address-of operator
// Note: two stars, not three
void init_capabilities(Capabilities **capabilities) {
for(int i=0;i<6;i++){
for(int j=0;j<8;j++){
printf("%d %d\n",i,j);
capabilities[i][j].room_capabilities = new RoomCapability[rooms_count];
}
}
}
Or, since you are coding in C++, not C:
// Assuming that result.capabilities and Capabilties::room_capabilities are declared
// vectors of the appropriate types ...
result.capabilities = std::vector<std::vector<Capabilities> >(std::vector<Capabilities>(8),6);
init_capabilities(result.capabilities);
void init_capabilities(std::vector<std::vector<Capabilities>& capabilities) {
for(int i=0;i<capabilities.size();i++){
for(int j=0;j<capabilties[i].size();j++){
printf("%d %d\n",i,j);
capabilities[i][j].room_capabilities.resize(rooms_count);
}
}
}
Declare
void init_capabilities(Capabilities ***capabilities)
as
void init_capabilities(Capabilities **capabilities)
and call by
init_capabilities(result.capabilities);
You just need to pass the pointer to your array structure, not a pointer to the pointer of your array structure.
Edit: And as others have pointed out, if you're going to use C++ you should really be using new as in:
result.capabilities = new (Capabilities *)[6];
for(int i=0;i<6;i++) {
result.capabilities[i] = new Capabilities[8];
}
init_capabilities(result.capabilities);
...
void init_capabilities(Capabilities **capabilities) {
for(int i=0;i<6;i++) {
for(int j=0;j<8;j++) {
capabilities[i][j].room_capabilities = new RoomCapability[rooms_count];
}
}
}
And don't forget to use delete[]. Better yet, do as Rob suggests and use the pre-defined C++ containers to handle this sort of thing. But if you really want to use unsafe pointers, what I have above should get it done for you.
You've got a whole host of problems here:
You allocate space for each individual Capability, then create a
new one, turning the allocated space into garbage
You treat
capabilities as a 2d array, when it is actually an array of pointers
to arrays
You pass the address of this overall array, but do
nothing to deference it in the function
Until you get straight what you're trying to do, HOW to do it will have to wait.