How to avoid a destructor being called twice in C++? - 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.

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

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.

C++ Segmentation Fault From Null Pointer Solution?

I'm getting a segmentation fault on this program, and I know it has something to do with a null pointer being dereferenced, but I'm not exactly sure which one is causing the error. I'm just not certain as to how to fix the error while maintaining the purpose of the original program - it will compile, but at runtime I get the segfault I was just talking about.
main:
#include "link.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
link * head_pointer = new link(NULL, NULL) ;
for (int i = 0; i < 10; i++) {
string new_string;
getline(cin, new_string);
string* pointer_to_input = new string(new_string);
link * current_link = new link(head_pointer, pointer_to_input );
head_pointer = current_link;
}
head_pointer -> printAll(*head_pointer);
return 42;
}
link:
#include <string>
#include <iostream>
#include "link.h"
using namespace std;
link::link(link * pointer_to_link, string * pointer_to_string)
{
next = pointer_to_link;
value = pointer_to_string;
}
link::~link() {
delete value;
delete next;
}
link * link::getNext() {
return next;
}
string * link::getString() {
return value;
}
int link::printAll(link link_to_print) {
cout << *link_to_print.getString() << endl;
if (link_to_print.next != NULL) {
return printAll(*link_to_print.getNext());
} else {
return 0;
}
}
Your destructor does look like an error, you shouldn't delete in destructor if you didn't allocate that in constructor:
link::~link() {
}
You should post your link.h to get more detailed explanation.
Without link.h it's not clear what else is wrong, however, there are also other problems:
link::printAll looks like a static method and should be called as: link::printAll(head_pointer);
you printAll should take by pointer, otherwise it it will create a copy of your link and delete it.
printAll has multiple issues as well. Probably it should have been something as follows:
void link::printAll(link *link_to_print)
{
if (!link_to_print)
return;
if (link_to_print->getString())
cout << *link_to_print->getString() << endl;
printAll(link_to_print->next);
}
and your main:
int main()
{
link * head_pointer = new link(NULL, NULL);
for (int i = 0; i < 10; i++) {
string new_string = str;
getline(cin, new_string);
string* pointer_to_input = new string(new_string);
link * current_link = new link(head_pointer, pointer_to_input);
head_pointer = current_link;
}
link::printAll(head_pointer);
return 42;
}
In short to avoid errors you shouldn't store pointers to strings in your link, you should just store strings themselves. Your links perhaps shouldn't assume ownership of other links:
struct link
{
link *next;
string value;
link(link *next, const std::string& value) : next(next), value(value) {}
link * getNext();
const std::string& getString() const;
static void printAll(link *link_to_print);
};
link * link::getNext() {
return next;
}
const string& link::getString() const {
return value;
}
void link::printAll(link *link_to_print)
{
if (!link_to_print)
return;
cout << link_to_print->getString() << endl;
printAll(link_to_print->next);
}
and your main:
int main()
{
link * head_pointer = new link(NULL, "");
for (int i = 0; i < 10; i++) {
string new_string;
getline(cin, new_string);
link * current_link = new link(head_pointer, new_string);
head_pointer = current_link;
}
link::printAll(head_pointer);
// TODO: now you need to walk head_pointer and delete all links manually.
return 42;
}
Once you learn how memory management works in general you should most likely redesign your link using some kind of smart pointer helper class, such as unique_ptr or shared_ptr. And off course, once you master linked list you should start using std::list.
link::printAll takes its argument by value, which has two important effects:
The argument inside the function is a second link object created by making copies of the same value and next pointer.
The copy has automatic storage duration and is destroyed at the end of the function call.
Therefore, you have double frees going on. In particular, both the copy made in the recursive call and the sub-link of the original link share the same value pointer, and both try to delete it. The second deletion causes undefined behavior.
The solution is to respect the rule-of-three and not allow shallow copies of raw pointers. There are two possible approaches for managing objects owned by pointer:
Write a copy constructor to go with your destructor, so the two deletes mentioned above act on two different copies of the value.
OR
Use a smart pointer, such as std::shared_ptr, so you don't have to write a destructor by hand at all.
Note that you need a pointer to implement the connection between objects in the linked list, but you do not need a pointer to store the data. Having a data member of type std::string, instead of std::string *, would be just fine and do the right thing when copied (It makes sense to think of std::string as a smart pointer to an array of characters, that just happens to also have some extra string-manipulation functions tacked on).

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.

C++ Stack datastructure. What's wrong with this piece of code?

so I'm currently trying to migrate my Java experience to C++ by implementing various Data Structures for the sake of having them implemented at least once.
Would you mind giving me some advise? The problem I am having is mainly concentrated around the pointers in push(int value) and especially pop(). As push seems to be working correctly I found myself struggling to get the correct value back when pop'ing things. What's the matter?
PS: I also think, that since I allocate my array space manually I'd need to delete it aswell. How do I do that?
#ifndef STACK_H
#define STACK_H
class Stack
{
private:
int *stackArray;
int elementsInArray;
int allocatedArraySize;
int alpha;
int beta;
public:
Stack();
void push(int aValue);
int pop();
bool isEmpty();
int size() const;
};
#endif
and the implementation:
#include <iostream>
#include "Stack.h"
Stack::Stack()
{
alpha = 4;
beta = 2;
elementsInArray = 0;
allocatedArraySize = 1;
stackArray = new int[1];
}
void Stack::push(int aValue)
{
if (elementsInArray == allocatedArraySize)
{
int temporaryArray[allocatedArraySize*beta];
for (int i = 0; i < elementsInArray; i++)
temporaryArray[i] = stackArray[i];
stackArray = temporaryArray;
allocatedArraySize *= beta;
}
elementsInArray++;
stackArray[elementsInArray] = aValue;
}
int Stack::pop()
{
int result = -INT_MAX;
if (elementsInArray == 0)
return result;
if (elementsInArray > 0)
{
result = stackArray[elementsInArray-1];
elementsInArray--;
if (elementsInArray <= allocatedArraySize/alpha)
{
int temporaryArray[allocatedArraySize/alpha];
for (int i = 0; i < elementsInArray; i++)
temporaryArray[i] = stackArray[i];
stackArray = temporaryArray;
allocatedArraySize /= beta;
}
}
return result;
}
bool Stack::isEmpty()
{
if (elementsInArray == 0)
return true;
return false;
}
int Stack::size() const
{
return allocatedArraySize;
}
For starters, you should be post incrementing the index on the array, so change:
elementsInArray++;
stackArray[elementsInArray] = aValue;
to:
stackArray[elementsInArray++] = aValue;
or:
stackArray[elementsInArray] = aValue;
elementsInArray++;
Second, when you create the new temp array you are doing it inside the if statement... therefore it is a local variable and placed on the system stack and lost after you exit the if statement. So change
int temporaryArray[allocatedArraySize*beta];
to:
int *temporaryArray = new int[allocatedArraySize*beta];
Third, add in the delete you were talking about by saving the original pointer from stackArray before copying the location of tempArray and then perform the delete after you've made the pointer copy.
Finally, you'll have to make similar changes to your pop function...
You are using an array on the stack (not your stack - the program execution stack). It's the one called temporaryArray in your push function. The address of that array will be invalid when you return from that function (because other functions will use the stack to hold other data).
what you want to do is allocate that array on the heap. This is memory that stays around for your program as long as you need it. To do this, you would allocate your temporaryArray like
int * temporaryArray(new int[allocatedArraySize*beta]);
Then, after copying the elements from your old array, you would delete it by using:
delete [] stackArray;
Do this before assigning the stackArray with the temporaryArray.
There may be other issues with your data structure, but you are doing the basic indexing correctly and incrementing / decrementing the current index appropriately (though I would suggest preferring to use the preincrement / decrement forms when not using the temporary as a good habit to get in - ie. ++elementsInArray / --elementsInArray).
well, i'm sure you already know that you have stack as a generic (c++ call it templates) in the STD library. Assuming you are doing this as a code kata, i would start writing it as a template, so it can't take object types others than integers.
Also, if you are going to write more of these low-level structures (as part of your kata), write a thin class where you delegate all allocation, reallocation and allocated size tracking, and use that instead of using arrays directly.