multithread segment fault destructors - c++

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_.

Related

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.

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.

Heap corruption when using delete/new in extra function

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.

loop for with class functions error when condition too high

Last time I'm constantly getting an error with for-loop.
The easiest way to show it is:
#include <iostream>
class Class
{
private:
int number;
public:
Class(int a);
void get();
};
Class::Class(int a)
{
number=a;
}
void Class::get()
{
std::cout<<number<<std::endl;
}
int main()
{
int amount=4;
Class* p[amount];
for(int i=0;i<amount;i++)
{
delete p[i];
p[i]=new Class(i);
}
for(int i=0;i<amount;i++)
{
p[i]->get();
}
return 0;
}
Program is returning 255, and while debugging I'm getting a SIGSEGV signal - segmentation fault.
I found one thing very strange: when amount=3 or less program works properly. I'm going to use it for over 700 elements, so I've found this quite disappointing.
I'm using Windows 7 and Code::Blocks 13.12 with GNU GCC Compiler.
What should I change in this program so that it works properly? I'm pretty sure that's only my small knowledge about c++ or something like that.
Thanks in advance.
Class* p[amount];
for(int i=0;i<amount;i++)
{
delete p[i];
p[i]=new Class(i);
}
You should remove the line delete p[i]; since the array p is not initialized yet.
You are consistently calling delete on pointers that don't point to dynamically allocated objects:
Class* p[amount]; // array of uninitialized pointers
delete p[i]; // oops
Here is what's going on (see comments):
// This allocates `amount` spots for pointers
Class* p[amount];
// Your pointers are not initialized yet
for(int i=0;i<amount;i++)
{
// You are trying to delete what they point to
delete p[i]; // <<== This is undefined behavior
p[i]=new Class(i);
}
You should not call delete until after you have allocated the objects being deleted. Otherwise, it's undefined behavior, i.e. your program may crash.
Finally, you need to delete the pointers after you are done with them to avoid memory leak. You could use a vector of smart pointers for that (recommended), or simply add another loop to your program, like this:
int amount=4;
Class* p[amount];
for(int i=0;i<amount;i++)
{
p[i]=new Class(i);
}
for(int i=0;i<amount;i++)
{
p[i]->get();
}
for(int i=0;i<amount;i++)
{
delete p[i];
}
initialize p[i] along with declaration.
Class* p[3] = {0}; delete has built in null check, with that you will not get any error
you should be getting error even when amount is 3 or less than three

C++ destructor of a class containing a vector of pointers

I have a class that looks like this :
#include <iostream>
#include <vector>
using namespace std;
class MyClass
{
vector<int*> V;
public:
MyClass();
MyClass(int n);
~MyClass();
};
MyClass::MyClass()
{
return;
}
MyClass::MyClass(int n)
{
int* T = new int[n];
for(int i=0; i<n; i++)
{
T[i]=i;
V.push_back(&(T[i]));
}
return;
}
MyClass::~MyClass()
{
for(int i =0; i<V.size(); i++)
delete V[i];
return;
}
int main()
{
MyClass C(5);
return 0;
}
What's wrong about my destructor? I get a "* glibc detected * ./a.out: free(): invalid pointer:..." error upon execution of this.
Do you think I should use ptr_vector? I don't know if I have the courage to learn about those.
Thanks in advance!
EDIT: Your intention is to have a vector of pointers, not arrays, so the problem is with your constructor:
int* T = new int[n];
for(int i=0; i<n; i++)
{
T[i]=i;
V.push_back(&(T[i]));
}
This doesn't create n pointers, but a pointer to n ints.
You should do:
for(int i=0; i<n; i++)
{
V.push_back(new int(i));
}
Before edit:
The problem isn't only in the destructor, but the constructor.
I'm assuming you want to push the array in the vector, in which case you need:
MyClass::MyClass(int n)
{
int* T = new int[n];
for(int i=0; i<n; i++)
{
T[i]=i;
}
V.push_back(T);
return;
}
You're also getting undefined behavior by calling
delete V[i];
instead of
delete[] V[i];
In your destructor, you're deleting pointers that were never allocated. You can only use delete (or delete[]) if there's a specific matching use of new (or new[]), and for n-1 of your int pointers, there is no such call.
If you want your vector to hold pointers to individual unrelated ints, then you need to use new to allocate each one individually. If they're always going to be in an array like this, then keep a pointer to that array in a member, and delete just that one pointer in your destructor.
You are allocating a contiguous block of memory with
int *T = new int[n];
You cannot delete single elements of this block. You can only delete the entire block at once.