Heap corruption when using delete/new in extra function - c++

In the following code sample Visual Studio gives me the error "A heap has been corrupted". At first the for-loop seems to work fine, but after 1 or 2 iterations it just crashes.
I feel that my function myReAllocate facilitates some sort of memory leak where it shouldn't (because when I comment it out, everything works fine). What exactly is going on? It seems like a very subtle error.
#include <iostream>
using namespace std;
class myClass{};
void myReAllocate(myClass* c)
{
delete c;
c = new myClass();
}
int main(void)
{
myClass *cc[10];
for (int i = 0; i < 10; i++){
cout << i << " attempt" << endl;
cc[i] = new myClass();
myReAllocate(cc[i]);
delete cc[i];
}
return 0;
}
I have tried adding a operator= but it didn't help either.
myClass operator=(myClass& right) {
myClass temp = right;
return *this;
}

myReAllocate gets the address of the myClass as parameter. You then free that address and allocate a new object and assign it to the local variable. This has no effect on the value of cc[i]. So when you then delete cc[i] you delete the already deleted object again.
If you want do to something like that then you need to pass the address of cc[i] (or reference to it) so you can change it:
void myReAllocate(myClass** c)
{
delete *c;
*c = new myClass();
}

I would go for reference instead of pointer as parameter:
void myReAllocate(myClass*& c)
{
delete c;
c = new myClass();
}
as this would not require client code change. Goswin's proposal requires the call to myReAllocate to be:
myReAllocate(&cc[i]);
while references allow it to be called without a change.

Related

multithread segment fault destructors

i have a segment fault when it calls the function unit_thread_data,Actually it is caused by ~Data(). thread1 is all right, but thread2 cause the segment fault, the whole code is as fallows:(forgive the poor code style), error info is double free or corruption. Other info: gcc5.4.0, centos7. any help? thank you very much!
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
class Data
{
public:
int* A_;
Data()
{
cout<<"111\n";
A_=NULL;
}
~Data()
{
cout<<"222\n";
if(A_) {
delete A_;
}
}
};
struct thread_data_t
{
Data* d;
};
void* _add(void* _pthread_data)
{
thread_data_t* pthread_data = (thread_data_t*) _pthread_data;
pthread_data->d->A_ = new int[2];
pthread_data->d->A_[0] = 1;
pthread_data->d->A_[1] = 2;
std::cout<<pthread_data->d->A_[0]+pthread_data->d->A_[1]<<endl;
return (void*)0;
}
void unit_thread_data(thread_data_t* pthread_data)
{
for(int i=0;i<2;i++)
{
delete[] pthread_data[i].d->A_;
delete pthread_data[i].d;
}
delete[] pthread_data;
}
int main()
{
int num_threads = 2;
pthread_t threads[num_threads];
thread_data_t* pthread_data = new thread_data_t[num_threads];
for(int i=0;i<num_threads; i++)
{
pthread_data[i].d = new Data();
}
for (int i=0; i<num_threads; i++) {
pthread_create(&threads[i], NULL, _add, (void*)(pthread_data+i));
}
for (int i=0; i<num_threads; i++) {
pthread_join(threads[i], NULL);
}
sleep(1);
unit_thread_data(pthread_data);
return 0;
}
delete[] pthread_data[i].d->A_;
This deletes the A_ member of your Data class, an int *.
Immediately afterwards, this happens:
delete pthread_data[i].d;
And this deletes the Data itself. Data's destructor then does the following:
if(A_) {
delete A_;
}
This then proceeds to attempt delete the same pointer. This should be delete[]d instead of deleted in the first place, but this is moot because this pointer is already deleted, and this tries to delete it a 2nd time.
This results in undefined behavior.
It is because you first delete member A_ here:
delete[] pthread_data[i].d->A_;
without assigning nullptr to A_ afterwards, and then you call delete A_; in the destructor.
Apart from that, in your code it is not clear who should be the owner of the memory allocated under A_ (functions _add and unit_thread_data, or a class itself), hence it is easy to do this kind of mistakes.
Quick fix (not recommended): just remove your destructor's body, and let your external functions _add and unit_thread_data manage the memory.
Better fix (recommended): think about who should be the owner of the allocated data (I would say class Data) and use std::unique_ptr if you can.
You need to assign NULL after deleting A_.

Deleting dynamic array in C++ causes an error

I have a class called Myclass. In the main function, I have created an array object for this class. Whenever I try to delete this dynamically allocated array, the visual studio will say, Error: Debug Assertion Failed!. Expression: is_block_type_valid(header->_block_use). Can you please tell me what is causing this or show me an example of fixing this issue.
#include <iostream>
using namespace std;
class Myclass
{
public:
void print()
{
cout << "Hello from Myclass" << endl;
}
};
int main()
{
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
// Call each object's print function.
for (int index=0; index < 3; index++)
{
obj[index]->print();
}
delete[] obj; //Error
return 0;
}
This:
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
is not a dynamically allocated array. It is an array with automatic storage, holding pointers to dynamically allocated objects. To properly clean up, you need:
delete obj[0];
delete obj[1];
delete obj[2];
Because every new must be matched with a delete, and you can only delete via delete[] something that was allocated via new[].
There is no need for any dynamic allocation here, just do:
Myclass obj[3] = {};
The delete[] operator should only be used for arrays created using the new[] operator, which your obj isn't. You have a fixed array of pointers to objects, each of which must be deleted as such:
for (int index=0; index < 3; index++)
{
delete obj[index];
}
Alternatively, you can create your object array using the new[] operator, then delete the array with delete[]:
int main()
{
Myclass* obj = new Myclass[3];
// Call each object's print function.
for (int index = 0; index < 3; index++) {
obj[index].print(); // Note: Use "." here, not "->"
}
delete[] obj;
return 0;
}
The variable obj is declared as an array with automatic storage duration with the element type Myclass *.
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
That is it is an array of pointers not a pointer.
Each element of the array is indeed a pointer that points to a dynamically allocated memory. So as the array contains three elements you need to call the operator delete three times for each element.
It is simpler to do that in the range-based for loop.
For example
for ( auto &item : obj )
{
delete item;
item = nullptr;
}
I think you allocated the array wrong.
You should write Myclass* obj = new Myclass[3];
The above answer is perfect.
I would only add this is not a good style code, if you "think in C++". This is a rather C style code.
First of all, when you are coding in C++ and is not obligued to use C-compatible code, be cautious whenever you see yourself using a C pointer.
In this case, if instead of using a C array of C pointers, you had used a std::vector of MyClass objects, the vector destructor would have called your class destructor for each element, which I think is what you wanted.
My suggestion: change the C array to std::vector and you will be happier. Look how you could have implemented it, using C++11 features and forgetting old C stuff:
#include <iostream>
using namespace std;
#include <vector>
class Myclass
{
public:
void print()
{
cout << "Hello from Myclass" << endl;
}
};
int main()
{
cout<<"Hello World" << endl;
vector<Myclass> obj(3);
// Call each object's print function.
for (auto instance : obj)
{
instance.print();
}
return 0;
}
In this case you don't even need to worry about deleting the objects, since the vector destructor will be called when the function goes out of scope, and it will take care of calling Myobjects' destructors. Much cleaner and safer code.
Or, in case performance is a very bottleneck for you and you need a static array, if you are using C++11 or later, you also can use std::array, a less "wild" option (https://en.cppreference.com/w/cpp/container/array).
So that is the tip I leave for you, if coding in C++, use the best this language can offer, and try to forget dangerous and wild old C features. C is good as a lightweight and simpler language, when you need it. But everyone knows it is dangerous (and you have just stumbled on it).
This book of the Bjarne focuses on teaching C++ from scratch, leaving behind the not always productive C legacy:
Programming: Principles and Practice Using C++

How to avoid a destructor being called twice in C++?

I'm testing out a class representing an dynamic array data structure I made for myself as practice with the language, but I ran into a problem where the destructor is called twice over, causing a heap corruption error.
So far, I have attempted to comment out some of the delete words. However, this leads to undefined behavior.
#include <iostream>
#include "windows.h"
#include <vector>
template<typename T> class Spider {
private:
T** pointer;
int maxSize;
int lengthFilled;
public:
//default constructor
Spider()
{
pointer = new T * [1];
maxSize = 1;
lengthFilled = 0;
}
//destructor
~Spider()
{
for (int i = 0; i < lengthFilled; i++)
{
pop();
}
delete[] pointer;
}
//Pushes an object in
void push(T thing)
{
if (lengthFilled == maxSize)
{
increaseSize();
}
T* thinggummy = &thing;
//then save its pointer in the functional array
pointer[lengthFilled] = thinggummy;
lengthFilled++;
}
//pops the array
void pop()
{
delete pointer[lengthFilled-1];
setSize(lengthFilled - 1);
lengthFilled--;
}
}
int main()
{
Spider<Spider<int>> test((long long)1);
for (int i = 0; i < 2; i++)
{
test.push(Spider<int>());
test.get(i).push(2);//this is implemented in the actual code, just omitted here
std::cout << test.get(i).get(0);
std::cout << "push complete\n";
}
system("pause");
return 0;
}
The expected results for this program should be:
2
push complete
2
push complete
Press any key to continue...
Instead, I get an critical error code in the debug log of "Critical error detected c0000374".
There are two issues here:
Like WhiteSword already mentioned, you are taking the address of a local variable when you do T *thinggummy = &thing. That is going to cause trouble since that address will be invalid as soon as you leave scope (unless maybe T resolves to a reference type).
You call delete on the things in the pointer array. However, these were not allocated via new. Instead they are just addresses of something. So you are trying to free something that was never allocted.

c++ segmentation error on array returning from method

I got the following strange behavior and I cant figure out why it keeps happening consider the following code:
class bar{
private:
std::string name;
public:
bar():name("bar"){};
std::string getName(){return name;};
};
class foo{
private:
bar local_arr[2];
bar** heapArr;
public:
foo(){};
void populate(){
cout<<&local_arr[0]<<endl; //first
cout<<local_arr[0].getName()<<endl; //second
heapArr = new bar*[2];
for(int i=0;i<3;i++){
heapArr[i] = new bar();
}
};
bar* getLocal(){
return local_arr;
};
bar** getHeap(){
return heapArr;
}
};
int main()
{
bar* b = new bar();
foo & f = *(new foo());
f.populate();
bar* local = f.getLocal();
bar** heap = f.getHeap();
cout<<&local[0]<<endl;//third
cout<<local[0].getName()<<endl;//last
return 0;
}
now the output I get is:
first - "0x1ea3c70"
second - "bar"
third "0x1ea3c70" (same address - same object)
last - "segmentation fault"
how can it happen it's obvious we are referring to the same object in memory, so why in one place the method works and in other I get this error...
The problem comes from the following code:
heapArr = new bar*[2];
for(int i=0;i<3;i++){
heapArr[i] = new bar();
}
heapArr is created as an array with only 2 elements, but the following for loop is trying to access the 3rd element, i.e. it's getting out of the bound of the array and then leads to UB, means anything is possible. For your case, it seems the memory got corrupted.
Change it to
for(int i=0;i<2;i++){
heapArr[i] = new bar();
}
Your program has undefined behavior because of the following lines in populate().
heapArr = new bar*[2]; // Allocate memory for 2 pointers
for(int i=0;i<3;i++){ // Using heapArray[2] accesses memory using a wrong index.
heapArr[i] = new bar();
}
Make sure that those numbers are same - both 2 or both 3.
heapArr = new bar*[2];
for(int i=0;i<2;i++){
heapArr[i] = new bar();
}
PS
I fully encourage use of the language's facility to manage dynamically allocated objects as a learning tool. However, if you are trying to get a working program that solves a real world problem, I discourage use of dynamically allocated memory in application code. You can use containers from the standard library to manage lists, sets, and maps of objects.

Program crashes whenever i run the commented code

Whenever i run the commented part of the constructor money the program crashes.
When i compile it, it does not throw any error as well.
Can someone tell me what is happening?
Also i am trying to implement the vending machine problem here.
i have removed some parts of the code which are working properly.
#include <iostream>
using namespace std;
class money
{
public :
int *max;
int *accepted_values = new int[10];
bool present;
int *deposited;
int i;
money()
{
}
money(int *a, int how_many)
{
//*max = how_many;
// for (i=0; i<how_many; i++)
// {
// accepted_values[i] = a[i];
// }
//*deposited = 0;
present = false;
}
};
class Vending_machine
{
public :
money *coins = new money(accepted_coins, 5);
//money *coins = new money();
int *amount_deposited = new int;
Vending_machine()
{
cout<<"Cool";
}
~Vending_machine()
{
delete amount_deposited;
}
};
int main()
{
Vending_machine a;
}
You are dereferencing the int pointers int *max and int *depositedin your constructor, without assigning a proper memory address first.
This will always crash, since it's undefined behaviour.
int* myPointer;
*myPointer = 10; // crashes
A pointer has always to point to a valid address first, before you can use it.
This could be the address of another variable:
int myInt;
int *myPointer = &myInt;
*myPointer = 10; // doesn't crash - myInt now is 10.
or it could be dynamically allocated and released.
int* myPointer = new int;
But in that case you'll have to take care that the memory is released once you are done.
delete myPointer;
A better solution is to use std::unique_ptr<>, which takes care of releasing its pointer on destruction.
But the best solution is not to use pointers at all, if they are not really necessary - especially if you don't know very exactly how pointers work. I assume in your example you could avoid pointers completely.