loop for with class functions error when condition too high - c++

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

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

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.

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.

Should i use delete[] in a function? [duplicate]

This question already has answers here:
Is not calling delete on a dynamically allocated object always a memory leak?
(6 answers)
Closed 6 years ago.
void work() {
int *p;
p=new int[10];
//some code....
}
I have a short question that in the work function, should i use delete[] operator? since when work function is over, p will be destroyed, which is wrong or right ? (My English is bad, i am sorry).
This will work as long as the code throws no exceptions...
void work() {
int *p;
p=new int[10];
//some code....
delete [] p;
}
This is better (but difficult to maintain):
void work1() {
int *p;
p=new int[10];
try {
//some code....
} catch(...) {
delete [] p;
}
delete [] p;
}
This is much better...
void work2()
{
auto p = std::unique_ptr<int[]>(new int[10]);
// some code...
// memory is automatically deleted
}
And this is how you should do it...
void work3()
{
auto v = std::vector<int>(10);
// some code...
}
You're right, if you have no reference to p outside of the function, e.g. a global variable, then you need to call delete [] p right inside of the function, otherwise the reference to the allocated memory you want to free is lost.
Yes, if integers are allocated using new int[10], you need to clean up using delete[], since it is an array.
Yes, you need to release the memory from new.
Alternatively with C++11, you can use smart pointer:
void work() {
std::unique_ptr<int[]> p{ new int[10] };
//some code....
// RAII will delete[] magically here
}
Alternatively, if you are using just few integers (10 in your case), that are known in compile time, you can do "normal" or static array. e.g.
void work() {
/* static */ int p[10];
//some code....
}
Alternatively, use std::vector:
void work() {
std::vector<int> p{10};
//some code....
// RAII will delete[] magically here
}
Alternatively, with C++11 if array size is known in compile time, use std::array:
void work() {
std::array<int,10> p;
//some code....
// RAII will delete[] magically here
}

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.