destructor is called continuesly [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Improve this question
I'm currently working on a game using OpenGL ES 2.0 on Android (in C++ using the NDK).
I have a class called "Drawable" which is my base class for drawing objects using OpenGL.
In the destructor of the class I have to clean up some buffers :
Drawable::~Drawable() {
LOGE("release");
releaseBuffers();
}
But the destructor is called endlessly (as in every loop of the thread), which messes up my drawing.
I'm kind of lost here and I could not find similar problems, so help is welcome!
Edit: Loop code is here : link
Edit2: I found one of the evil calls:
In my player class I have this call:
currentWeapon->draw(this);
to
void Weapon::draw(Player* p)
If I comment this, the spam is gone.

There are very few ways a destructor gets called:
1) You create an instance of Drawable on the stack, and it falls out of scope. If this is done in a tight loop, the object will fall out of scope and be destroyed at each iteration of the loop. For example:
for (size_t i = 0; i < 100; ++i)
{
Drawable d;
}
Here, 100 instances of Drawable will be created and destroyed, at the beginning and end of every loop.
2) You delete a dynamically-allocated Drawable:
for (size_t i = 0; i < 100; ++i)
{
Drawable* d = new Drawable;
delete drawable;
}
3) You call the destructor explicitly:
Drawable* b = new (buffer) Drawable;
b->~Drawable()
Note that #3 uses "placement new" and is highly unlikely.
Objects can be destroyed at suprising times when they are in a container such as a vector. Consider:
vector <Drawable> drawables;
for (size_t i = 0; i < 10000; ++i)
{
Drawable d;
drawables.push_back (d);
}
You will notice potentially many destructor calls when you run this code. When you push_back, a copy is potentially made and the original (d here) is destroyed. Also, when the vector reaches capacity it has to reallocate, which results in every item being copied again, and the originals destroyed.
Objects can also be destroyed at suprising time in the face of temporaries and unexpected copies. Consider:
void DoSomething (Drawable d)
{
}
int main()
{
Drawable d;
for (size_t i = 0; i < 1000; ++i)
{
DoSomething (d);
}
}
This is a naive example because the compiler will likely elide the temporaries in this case. But since DoSomething() takes a Drawable by-value a copy of the original could be made. Depending on other code, the compiler might not even be able to elide this copy.

Related

how to accessing vectors in a loop [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am programming a Space Invaders clone and I am struggling at creating the bullets.
Whenever I click Space a bullet is supposed to be added to the vector and then I want to move them via a loop, but I dont understand how to create and handle it the proper way.
vector<Bullet> bullets(MAXBULLETS);
int bulletcounter = 0;
while (1) {
Sleep(10);
for (int i = 0; i < sizeof(bullets)-1; i++) {
bullets[i].Move(0, 1);
}
if (GetAsyncKeyState(VK_SPACE)) {
Bullet *bullet = new Bullet();
bullets[bulletcounter] = bullet; // Here is the error
bulletcounter++;
}
bullets is a vector that holds objects of type Bullet.
Bullet *bullet = new Bullet();
bullets[bulletcounter] = bullet; // Here is the error
Your bullet here is of type Bullet*. The two incompatible types get you the error.
To fix this, stop using a pointer and just instantiate an object:
Bullet bullet;
This creates a Bullet object using the parameterless constructor that you can then add to your bullets.
Do note though, that this currently does nothing since you initialize your vector giving it a predefined size bullets(MAXBULLETS), this already creates MAXBULLETS default constructed objects for you, ready to use:
Constructs the container with count default-inserted instances of T.
No copies are made.
Side note : stop using new altogether; this isn't Java or C#. If you need a dynamically allocated object then use a smart pointer. Most of the time, though, an object automatic-storage duration will do just fine.
My proposal
vector<Bullet> bullets;
while (1)
{
Sleep(10);
for (int i = 0; i < bullets.size(); i++)
{
bullets[i].Move(0, 1);
}
if (GetAsyncKeyState(VK_SPACE))
{
bullets.push_back(Bullet());
}

Delete[] causing crash in C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am working with the same code from this code from my previous SO post but I have made several changes. My problem is that I have a dynamic array that I call delete[] on inside of my operator overload for the copy constructor and I get the error below.
Exception thrown at 0x0F7063BB (ucrtbased.dll) in Lab3.exe: 0xC0000005: Access violation reading location 0xCCCCCCBC.
If there is a handler for this exception, the program may be safely continued.
Can anyone help me understand why?
I checked the related questions but there are different errors than from what I'm seeing and I haven't found a result in my google search. I am using C++ 11 on visual studio 2015.
#include "ListArray.h"
template < typename DataType >
List<DataType>::List ( int maxNumber )
{
//maxSize = MAX_LIST_SIZE; maybe???
maxSize = maxNumber;
dataItems = new DataType[maxSize];
size = maxSize - 1;
cursor = 0; // sets cursor to the first value in list
for (; cursor <= size; cursor++)
dataItems[cursor] = 1;
cursor = 0;
}
template < typename DataType >
List<DataType>::List ( const List& source )
{
*this = source; // should be handled by copy constructor
}
template < typename DataType >
List<DataType>& List<DataType>::operator= ( const List& source )
{
if (this != &source)
{
maxSize = source.maxSize;
size = source.size;
cursor = source.cursor;
delete []dataItems; // clears dataItems, weird run-time error here. Why?
dataItems = new DataType[size];
for (int count = 0; count < size; count++)
dataItems[count] = source.dataItems[count];
}
else
// do nothing, they are the same so no copy is made
return *this;
}
template < typename DataType >
List<DataType>::~List ()
{
maxSize = 0;
size = 0;
cursor = -1;
delete[] dataItems;
}
Edit: I initially posted several other incomplete functions also a part of the program I am trying to build. I meant only to include the ones that I know are generating my problem. My apologies for the bad post.
If you're going to use the assignment operator to make your copies, you need an empty object to start with, otherwise operator= will fail horribly when it tries to clean up the old contents before replacing them (as Sam explained in his answer and MikeCAT mentioned in his comment -- give them upvotes -- and what Dieter told you on your earlier question).
Since C++11, constructor chaining aka constructor delegation is possible, like this:
template < typename DataType >
List<DataType>::List ( const List& source )
: List() /* default construct object before proceeding */
{
*this = source; // should be handled by copy constructor
}
another option is to make the copy constructor responsible for creating a default object itself, and this is what would be needed in C++98 and C++03:
template < typename DataType >
List<DataType>::List ( const List& source )
: maxSize(0), dataItems(NULL), size(0) // initialize members
{
*this = source; // should be handled by copy constructor
}
But this is duplicating the function of the default constructor, so as long as your compiler has support for the C++11 feature, prefer to call the existing one.
The details of constructor delegation... get complicated. Among other things, normally any exception thrown from inside an object constructor prevents the object from ever existing, and the destructor is not called. When delegation is used, then the object becomes live when any constructor completes, and an exception inside a wrapper constructor will face an object that's already alive and call the destructor for you. This behavior may or may not be desirable, but it's something to watch out for because exception-safety is important in modern C++.
The copy constructor does not initialize anything in the new instance of the class. All it does is call the assignment operator.
The assignment operator executes:
delete []dataItems;
Since dataItems has not been initialized, this results in undefined behavior, and an immediate crash.

pointer being freed was not allocated (suspected due to double deletion) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Every time I try to delete an object in my array of pointers plantLayout[][], I get the error "pointer being freed was not allocated". I debugged it and realized that every time that I step into the ~Plant() destructor it goes into the malloc files and then back to the ~Plant() destructor, and then back into the malloc files, and then it gets that error. I am assuming that it is because of a double deletion error, but I can not seem to figure out where I am going wrong.
Below is the relevant code:
MainWindow.h: (relevant code)
const static int rows = 5;
const static int columns = 10;
Plant *plantLayout[rows][columns-1];
Plant *seedingPlant;
Plant.h
#ifndef PLANT_H
#define PLANT_H
#include <QString>
#include <QGraphicsPixmapItem>
#include <sun.h>
class Plant
{
public:
Plant();
int x, y;//top left corner of the plant's lawn piece
int width, height;//of lawn piece
int plant, cost, life, range, damage, splash, slow, bomb, sun, need, row, column;
static int statCost;
double rate, seeding;
QString name;
QGraphicsPixmapItem *icon;
QString file;
Sun sunObject;
bool active;
virtual void beginAttackingSequence();
virtual void explosion();
};
#endif // PLANT_H
Plant.cpp
Plant::Plant()
{
this->sun = 0;
this->active = false;
this->height = 60;
this->width = 60;
this->sunObject.onScreen = false;
}
void Plant::beginAttackingSequence(){
}
void Plant::explosion(){
}
I assign the set the seeding plant equal to a new SunFlower() which is a subclass of Plant
seedingPlant = new SunFlower();
and then later on I assign a certain element of the plantLayout[][] array to the seedingPlant.
plantLayout[r][c] = seedingPlant;
at later points in the program I reinitialize the seedingPlant to be another different subclass of the Plant.
if(plantLayout[r][c] != NULL){
delete plantLayout[r][c];
}
I checked if that element is equal to null, which is what lead me to believe that it was a double delete that was causing the error!
Any help would be greatly appreciated! Thanks in advance!
You don't have all of the code posted, but a few things I can suggest:
You mentioned that SunFlower is a subclass of Plant. If you have polymorphic inheritance, you always want to have a virtual destructor (see C++ FAQ 20.7 for more info). In your case, add the following to the Plant declaration:
virtual ~Plant();
and add an implementation for it in Plant.cpp:
Plant::~Plant()
{
}
You're checking for NULL before invoking delete. You do not need to do that (and it's considered bad style). delete plantLayout[r][c]; by itself is just fine. See C++ FAQ 16.8 for more info.
Ensure that plantLayout is initialized to 0. e.g., in the constructor for MainWindow, you'll probably want:
for (int r = 0; r < rows; ++r)
for (int c = 0; c < columns-1; ++c)
plantLayout[r][c] = NULL;
My suspicion is that the "pointer being freed was not allocated" error is due to you invoking delete plantLayout[r][c] when plantLayout[r][c] is uninitialized (so it may contain some seemingly random value).

Having run time error with "delete[]" [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I was trying to program my own List class on C++.
Here is the code:
template <class T>
class List
{
private:
T *value, *valueHelper;
int valueSize;
public:
int size;
List()
{
valueSize = 2;
value = new T[valueSize];
size = 0;
}
void Add(T val)
{
size++;
if (size > valueSize)
{
valueSize *= 2;
valueHelper = new T[valueSize];
memcpy(valueHelper, value, sizeof(T) * (size - 1));
delete[](value);
value = valueHelper;
}
value[size - 1] = val;
}
void Clear()
{
delete[](value);
size = 0;
valueSize = 2;
value = new T[valueSize];
}
T & operator[](int P)
{
return value[P];
}
};
The problem appered when I used a class variable on this List Class.
When I do Clear to delete some memory, there are a run time error appers.
I have trying to check what cause this problem and I have find out that this line on the function Clear() is the error line:
delete[](value);
I can not understand, why?
I'm just guessing here, but it could be likely it is because you will have copies made of the List instance, for example by returning it from a function or passing it as a non-reference argument to a function.
Copying of objects are implemented by the default copy-constructor generated by the compiler, but it only does shallow copying, meaning it will copy the pointers but not what they point to. So then you will have two copies with pointers pointing to the same memory, and when one object deletes that memory the others pointer will be invalid.
You also have a memory leak in that you don't have a destructor, so when an instance goes out of scope then you loose the allocated memory forever.
You should also read about the rule of three.

How do I avoid destructor stack overflow with deep nested data structure in C++?

int count;
class MyClass {
std::shared_ptr<void> p;
public:
MyClass(std::shared_ptr<void> f):p(f){
++count;
}
~MyClass(){
--count;
}
};
void test(int n){
std::shared_ptr<void> p;
for(int i=0;i<n;++i){
p = std::make_shared<MyClass>(p);
}
std::cout<<count<<std::endl;
}
int main(int argc, char* argv[])
{
test(200000);
std::cout<<count<<std::endl;
return 0;
}
The above program causes stack overflow under "release" build in Visual Studio 2010 IDE.
The question is: if you do need to create some data structure like the above, how to avoid this problem.
UPDATE: Now I have seen one meaningful answer. However this is not good enough. Please consider I have updated MyClass to contain two (or more) shared_ptrs, and each of them can be an instance of MyClass or some other data.
UPDATE: Somebody updated the title for me and saying "deep ref-counted data structure", which is not necessary related to this question. Actually, shared_ptr is only a convenient example; you can easily change to other data types with the same problem. I also removed the C++11 tag because it is not C++11 only problem as well.
Make the stack explicit (i.e. put it in a container on the heap).
Have non-opaque pointers (non-void) so that you can walk your structure.
Un-nest your deep recursive structure onto the heap container, making the structure non-recursive (by disconnecting it as you go along).
Deallocate everything by iterating over the pointers collected above.
Something like this, with the type of p changed so we can inspect it.
std::shared_ptr<MyClass> p;
~MyClass() {
std::stack<std::shared_ptr<MyClass>> ptrs;
std::shared_ptr<MyClass> current = p;
while(current) {
ptrs.push_back(current);
current = current->p;
ptrs.back()->p.reset(); // does not call the dtor, since we have a copy in current
}
--count;
// ptrs dtor deallocates every ptr here, and there's no recursion since the objects p member is null, and each object is destroyed by an iterative for-loop
}
Some final tips:
If you want to untangle any structure, your types should provide an interface that returns and releases all internal shared_ptr's, i.e something like: std::vector<shared_ptr<MyClass>> yieldSharedPtrs(), perhaps within a ISharedContainer interface or something if you can't restrict yourself to MyClass.
For recursive structures, you should check that you don't add the same object to your ptr-container twice.
Thanks to #Macke's tips, I have an improved solution like the following:
~MyClass(){
DEFINE_THREAD_LOCAL(std::queue< std::shared<void> >, q)
bool reentrant = !q.empty();
q.emplace(std::move(p)); //IMPORTANT!
if(reentrant) return;
while(!q.empty()){
auto pv = q.front();
q.pop();
}
}
DEFINE_THREAD_LOCAL is a macro that defines a variable (param 2) as specified type (param 1) with thread local storage type, which means there is no more than one instance for each running thread. Because thread_local keyword is still not available for mainstream compilers, I have to assume such a macro to make it work for compilers.
For single thread programs, DEFINE_THREAD_LOCAL(type, var) is simply
static type var;
The benefit of this solution is it do not require to change the class definition.
Unlike #Macke's solution, I use std::queue rather than std::stack in order to keep the destruction order.
In the given test case, q.size() will never be more than 1. However, it is just because this algorithm is breadth-first. If MyClass has more links to another instance of MyClass, q.size() will reach greater values.
NOTE: It is important to remember use std::move to pass p to the queue. You have not solved the problem if you forgotten to do so, you are just creating and destroying a new copy of p, and after the visible code the destruction will still be recursive.
UPDATE: the original posted code has a problem: q is going to be modified within pop() call. The solution is cache the value of q.front() for later destruction.
If you really have to work with such an odd code, you can increase the size of your stack. You should find this option in the project properties of Visual Studio.
As already suggested, I must tell you that this kind of code should be avoided when working with a large mole of data structures, and increasing the stack size is not a good solution if you plan to release your software. It may also terribly slow down your own computer if you abuse this feature, obviously.