Instantiation:
weapons.push_back(new Pistol());
weapons.push_back(new Rifle());
weapons.push_back(new Shotgun());
destructor, when the first delete happens, the code breaks. This happens when I close the program.
Brain::~Brain()
{
for (unsigned int i = 0; i < weapons.size(); i++)
{
delete weapons[i]; // this is where the code breaks
}
}
I get a warning:
Unhandled exception at 0x0096371f in D3D10DEMO.exe: 0xC0000005: Access violation reading location 0x000002ce.
weapons is this:
weapons(vector<Gun*>())
Edit - I have deleted much of the code from this question but I have also cut down my program so as to reproduce the problem in a much smaller solution here:
http://dl.dropbox.com/u/13519335/D3D10DEMO_0.25.MinRep.zip
You haven't defined virtual destructors for your weapon classes.
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7
You problem is the definition of
class Brain : public Entity
{
private:
std::vector<Gun*> weapons;
and the ownership of Gun* by Brain object.
Brain::~Brain()
{
for (unsigned int i = 0; i < weapons.size(); i++)
{
delete weapons[i];
}
}
If a Brain is copy constructed the delete will be called multiple times deleting the same Gun from different weapons vector. And a Brain temporary is created when you add your Agents (Agent being a derived class of Brain) like so in main function.
int main()
{
Level* level;
std::vector<Agent> agents;
level = new Level(agents);
for (int i = 0; i < 1; i++)
{
//TODO - health is a pointless parameter here
agents.push_back(Agent(100, *level, agents, level->Pickups(), D3DXCOLOR(1.0F, 0.4f, 0.4f, 1.0f)));
}
delete level;
}
If you implement a copy constructor for Brain that clones the Gun* vector you should be ok. Alternative you should use shared_ptr<Gun> in your vector so that you don't have to delete them at all.
To summarize your problem boils down to
class Foo{};
class Bar
{
public:
Bar()
{
mFooVec.push_back( new Foo() );
mFooVec.push_back( new Foo() );
}
~Bar()
{
for( unsigned int i = 0;i < mFooVec.size(); ++i )
{
delete mFooVec[i];
}
}
std::vector<Foo*> mFooVec;
};
int main()
{
Bar x;
Bar y = x;
return 0;
}
Here both Bar x and y have the same two Foo* in their mFooVec
Related
I wrote:
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) { // allocation failed for one node (Doesn't throw any exception)
~UnLabeledList();
delete[] SegArray;
throw;
}
SegArray[i] = NOT_INIT;
}
};
};
In case one allocation failed I want to destroy the object (since it has previously allocated nodes) for example when allocation fails at i==5. How can I call the d'tor of UnLabeledListto prevent memory leak?
You should never call a destructor yourself to clean up things. The language rules take care of it.
It is recommended to use standard classes like std::vector and std::list rather than raw arrays/pointers and homebrew lists. The standard classes already take care of exceptions and cleanup, so your class should look something like
class image {
public:
std::list<std::pair<int, int>> UnLabeledList;
std::vector<int> SegArray;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(Segments, NOT_INIT), TotalSegments(Segments) {
for (int i = 0; i < Segments; ++i) {
UnLabeledList.push_back({i, NOT_INIT});
}
};
};
You can't directly invoke the destructor of the UnLabeledList member like that.
If the image constructor throws an uncaught exception, the UnLabeledList member will be destructed automatically, if it was successfully constructed before the exception was thrown.
The correct solution is to implement a clear() method in the linked_list class, which you can call whenever needed, including in the copy constructor and destructor. For example:
template<...>
class linked_list {
// ...
public:
linked_list() {
// initialize the list as needed...
}
linked_list(const linked_list &src) : linked_list() {
for (each node in src) {
if (!push_back(...)) {
clear();
throw ...;
}
}
}
~linked_list() {
clear();
}
linked_list& operator=(const linked_list &rhs) {
// clear and copy the list as needed...
}
void clear() {
// free nodes as needed...
}
node* push_back(...) {
// add new node as needed...
return ...; // nullptr on error
}
//...
};
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw ...; // <-- UnLabeledList::~linked_list() called automatically!
}
SegArray[i] = NOT_INIT;
}
~image() {
delete[] SegArray;
} // <-- UnLabeledList::~linked_list() called automatically!
};
You also can't call a parameter-less throw; outside of an active catch handler. Outside of a catch, you must throw an actual value/object explicitly.
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw std::runtime_error("can't push a new node");
}
struct StructA {
StructA(parameters) { ... } //StructA onstructor
};
struct StructB {
StructA *pObjectA;
int counter = 0;
void function() {
if (counter < 1) { pObjectA = new StructA[100]; }
pObjectA[counter] = *new StructA(parameters); //Memory leak here
counter++;
}
};
struct StructC {
StructB objectB;
~StructC() { //StructC destructor
delete[] objectB.pObjectA;
objectB.pObjectA = NULL;
}
};
int main() {
StructC objectC;
for (int i = 0; i < 900; i++) {
objectC.objectB.function();
}
return 0;
} //Struct C destructor here
I need to create an object array and then, with each call to objectB.function(), to pass specific parameters to the constructor of StructA. The code above works perfectly, except for the memory leak, which I am unable to get rid of.
My guess is that the StructC destructor deletes only the object array, not each *new StructA(parameters). I tried to play around with pointers and delete[] a little bit, but all I got was access memory violation errors. This is the only way I can think of that works. All help appreciated.
A class destructor should release resources that were acquired in its constructor. It seems like you wanted to defer deleting an array allocated in one class to the destructor of a second class. Thats never a good idea. In the best case you dont have to do anything in the destructor because you use automatic storage (means what the name suggest: memory is managed automatically).
Your code could look like this:
struct StructA {
StructA(parameters) { ... } //StructA onstructor
};
struct StructB {
std::vector<StructA> pObjectA;
int counter = 0;
void function() {
if (counter < 1) { pObjectA.reserve(100); }
pObjectA.emplace_back(parameters);
counter++;
}
};
struct StructC {
StructB objectB;
};
int main() {
StructC objectC;
for (int i = 0; i < 900; i++) {
objectC.objectB.function();
}
return 0;
}
Note that I tried to keep the structure as is maybe there are other things to change. For example you dont need counter, as you can use std::vector::size to query the number of elements in the vector.
PS: As you already noticed, this is a memory leak:
pObjectA[counter] = *new StructA(parameters); //Memory leak here
It is not really clear why you wrote that code in the first place. The idomatic way to create an object of type StructA is StructA a; (no new!).
As you correctly assumed, memory leaks are caused by not properly cleaning up all new with corresponsing delete. However in idiomatic C++ there's no use to use new and delete directly.
Use std::vector, std::shared_ptr and std::unique_ptr to let RAII keep track of dynamically created objects, references to them and when to clean up. Not only is it more robust, it's also a lot shorter and easier to read.
With your code's general overall structure:
#include <memory>
#include <vector>
struct StructA {
};
struct StructB {
std::vector<std::shared_ptr<StructA>> objectAs;
void function() {
objectAs.push_back(
std::make_shared<StructA>( /*parameters*/ )
);
}
};
struct StructC {
StructB objectB;
};
int main() {
StructC objectC;
for (int i = 0; i < 900; i++) {
objectC.objectB.function();
}
return 0;
}
I have two Classes, Player and Game.
class Game
{
private:
int maxPlayer;
Player** playersArray;
public:
Game(int maxPlayer);
~Game();
}
Each index in playersArray consists of pointers to class Player.I'm not sure though how to make the constructor and destructor of the Class Game. This is my first try but the code isn't working any idea?
Game::Game(int maxPlayer)
{ this->playersArray = new Player*[maxPlayer];
for(int i=0;i<maxPlayer;i++)
{
playersArray[i]=NULL;
}
}
Game::~Game() {
for(int i=0;i<maxPlayer;i++)
{
delete[] *playersArray[i];
}
delete (playersArray);
}
It has been along time since I have programmed in C++. The only error I see for sure is that the constructor has a parameter maxPlayer and never touches the member variable maxPlayer. The destructor uses the member variable maxPlayer, which probably has never been initialized. The constructor ought to assign the parameter to the member variable.
When you delete an array you are supposed to use delete[] but you use delete for a single object. So, I think you have them swapped.
OK, since I did not get response to my comment, let me try this: If you modify your code as shown below, does it do what you expect it to do?
class Player
{
};
class Game
{
private:
int maxPlayer;
Player** playersArray;
public:
Game(int maxPlayer);
~Game();
};
Game::Game(int maxPlayer)
{
this->maxPlayer = maxPlayer;
this->playersArray = new Player*[maxPlayer];
for (int i = 0;i<maxPlayer;i++)
{
playersArray[i] = NULL;
}
}
Game::~Game() {
for (int i = 0;i<maxPlayer;i++)
{
delete playersArray[i];
}
delete[] playersArray;
}
int main()
{
Game g(10);
return 0;
}
I'm having trouble transferring some data contained in a vector between my functions. The situation is as follows:
void generateObjects(std::vector<MyClass> &objects)
{
objects.clear();
//Fill objects vector
std::vector<MyClass> p;
//This 4-line pattern is repeated a number of times to generate all objects and store them in variable 'objects'
p.clear();
generateSomeOfTheObjects(p); //p is again passed by ref. in/out parameter
for(uint j = 0; j < p.size(); p++){
objects.push_back(p[j]);
}
//Print some members of the objects - works fine
for(uint i = 0; i < objects.size(); i++){
printf("%f ",objects[i].mymember->myElm);
}
}
int main()
{
std::vector<MyClass> objects;
generateObjects(objects);
//Print size of vector - size is correct it is the same as it is in generateObjects func
printf("%lu\n",objects.size());
//Again print members of the objects - some members are retained after the function call, some are lost.
//The one below doesn't work, mymember is a pointer to another object and its member myElm seems not initialized.
for(uint i = 0; i < objects.size(); i++){
printf("%f ",objects[i].mymember->myElm);
}
//Here I need to pass the objects to another read-only function
...
}
I have searched the internet for similar cases and actually found many, but I couldn't apply the same fixes to my code. I'm trying to reach a member of an object pointed to by a member of a MyClass instance (objects[i].mymember->myElm) What possibly am I missing here?
Probably the error lies in the implementation of MyClass. I'd say that this class contains some pointer that is initialized with the address of a local variable, so when you return from some of the functions that pointer points to a destroyed object.
That would undefined behavior but it may work by chance. When you return from the first function, the stack memory is finally overwritten and your data is lost.
UPDATE: Thanks to the insight by #chris in the comments below, the most likely reason is that your MyClass does not have a copy constructor, but it does have a pointer member.
Something like this:
class MyClass
{
public:
Member *mymember;
MyClass()
{
mymember = new Member;
}
~MyClass()
{
delete mymember;
}
};
Now what happens if you use the compiler generated default copy constructor (or the copy operator)?
void foo()
{
MyClass a;
{
MyClass b(a);
}
//a.mymember is no longer valid
}
Both a and b share the same pointer mymember, so when one of them is destroyed, the mymember is deleted and the other one holds a dangling pointer.
That's why we have the rule of three. It states:
Whenever you define a non-default destructor, you most likely will want also a non-default copy-constructor and a non-default copy-operator.
Now you have to decide if you want to share the ownership of the mymember or if you want to copy it. The first one is best done with smart pointers (shared_ptr) and the second one with deep copy.
For example, deep copy:
class MyClass
{
public:
Member *mymember;
MyClass()
{
mymember = new Member;
}
MyClass(const MyClass &c)
{
mymember = new Member(c.mymember);
}
MyClass &operator=(const MyClass &c)
{
if (this != &c) //be aware of self-copy
{
delete mymember;
mymember = new Member(c.mymember);
}
return *this;
}
~MyClass()
{
delete mymember;
}
};
And with shared pointers:
class MyClass
{
public:
std::shared_ptr<Member> mymember; //or boost::shared_ptr if old compiler
MyClass()
:mymember(new Member)
{
}
//no custom-made destructor -> no rule of 3
};
Perhaps unrelated to you question, but this:
void generateObjects(std::vector<MyClass> &objects)
{
objects.clear();
std::vector<MyClass> p;
p.clear();
generateSomeOfTheObjects(p);
for(uint j = 0; j < p.size(); p++){
objects.push_back(p[j]);
}
for(uint i = 0; i < objects.size(); i++){
printf("%f ",objects[i].mymember->myElm);
}
}
Is the same as this:
void generateObjects(std::vector<MyClass> &objects)
{
objects.clear();
generateSomeOfTheObjects(objects);
std::reverse(objects.begin(), objects.end());
for(uint i = 0; i < objects.size(); i++) {
printf("%f ",objects[i].mymember->myElm);
}
}
You copy issues, as #rodrigo mentioned, is that you are not doing deep copies with your copy constructors.
I have a problem with a destructor of struct Heap. Even just adding one, and not using it, creates a runtime exception (memory access). It's second day I try to do it and tomorrow is a deadline.
struct Heap
{
int n;
int* tab;
int* numerWKopcu;
Heap () { n=0; }
Heap (int size) { this->tab = new int[liczbaDomow]; n=0; this->numerWKopcu = new int[2000100];}
int max() { return tab[1]; }
bool empty() { return n==0; }
bool insert(int x)
{
n++;
tab[n]=x;
this->numerWKopcu[x] = n;//ZMIANA
upHeap(n);
return true;
}
bool delMin()
{
if (n<1) return false;
this->numerWKopcu[tab[n]] = 1; //ZMIANA
tab[1]=tab[n]; n--;
downHeap(1);
return true;
}
void upHeap(int x){
int p;
int mem = tab[x];
while (x>1)
{
p=x/2;
if (color[mem]>color[tab[p]]) break;
this->numerWKopcu[tab[p]] = x; //ZMIANA
tab[x]=tab[p];
x=p;
}
this->numerWKopcu[mem] = x;//ZMIANA
tab[x]=mem;
}
void downHeap (int x)
{
int s=2*x;
int mem=tab[x];
while(s<=n)
{
if (s+1<=n && color[tab[s]]>color[tab[s+1]])
s++;
if (color[mem]>color[tab[s]])
{
this->numerWKopcu[tab[s]] = x; //ZMIANA
tab[x]=tab[s];
x=s;
s=2*x;
}
else break;
}
this->numerWKopcu[mem] = x;//ZMIANA
tab[x]=mem;
}
void write ()
{
for (int i=1;i<=n;i++) printf ("%d) %d\n", i, tab[i]);
printf ("\n");
}
void build()
{
int s = n;
for (s=n/2; s>=1; s--) downHeap(s);
}
/ ~Heap() {
delete []this->numerWKopcu;
delete []this-> tab;
};
};
The code is a bit hard to read, but I see two problems:
You aren't initialising the pointers to null in the default constructor, so destroying a default-constructed object gives undefined behaviour;
You don't define or remove the copy constructor and copy assignment operator (as you should always do if you define a destructor, per the Rule of Three), so destroying a copied object gives undefined behaviour.
It's also possible that you're accessing memory outside the array bounds; a memory debugging tool such as valgrind can help you determine whether that's happening.
The simplest solution is to replace your manually-managed arrays with std::vector; then you won't need to worry about writing your own destructors or copy semantics. You can also use at() rather than [] (at least in a debug variant) to give range-checked access.
You are not initializing pointers in default constructor. If you try to destroy default constructed Heap it will try to delete random memory areas in destructor and will definitely break.