#ifndef DELETE
#define DELETE(var) delete var, var = NULL
#endif
using namespace std;
class Teste {
private:
Teste *_Z;
public:
Teste(){
AnyNum = 5;
_Z = NULL;
}
~Teste(){
if (_Z != NULL)
DELETE(_Z);
}
Teste *Z(){
_Z = new Teste;
return _Z;
}
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
int AnyNum;
};
int main(int argc, char *argv[]){
Teste *b = new Teste, *a;
a = b->Z();
cout << "a->AnyNum: " << a->AnyNum << "\n";
b->Z(new Teste);
cout << "a->AnyNum: " << a->AnyNum << "\n";
//wdDELETE(a);
DELETE(b);
return 0;
}
I would like to know if there is a memory leak in this code
it works ok, the *a is set twice and the AnyNum prints different numbers on each cout <<
but I wonder what happened to the _Z after the setter(new Teste), I don't have much knowledge in pointers/references yet, but for the logic I guess it is being swapped for the new variable
if it is leaking, is there anyway to accomplish this without having to set a to _Z again?
because the address didn't change, just the direct memory allocated
I was going to use *& instead of just pointers, but would it make difference?
There is a memory leak on this line:
b->Z(new Teste);
because of the definition of the function:
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
It looks like Z without arguments was supposed to be a getter and with arguments a setter. I suspect you meant to do:
void Z(Teste *value){
value->AnyNum = 100;
_Z = value;
}
(note the third line) That is, assign the pointer "value" to the pointer "_Z" instead of copy what value pointed at over what Z pointed at. With that, the first memory leak would be resolved, but the code would still have one since _Z could have been holding a pointer. So you'd have to do:
void Z(Teste *value){
value->AnyNum = 100;
delete _Z; // you don't have to check for null
_Z = value;
}
As mentioned in another comment, the real solution is to use smart pointers. Here's a more modern approach to the same code:
using namespace std;
class Teste {
private:
boost::shared_ptr<Teste> Z_;
public:
Teste() : AnyNum(5), Z_(NULL)
{ }
boost::shared_ptr<Teste> Z()
{
Z_.reset(new Teste);
return Z_;
}
void Z(boost::shared_ptr<Teste> value)
{
value->AnyNum = 100;
Z_ = value;
}
int AnyNum;
};
int main(int argc, char *argv[]){
boost::shared_ptr<Teste> b = new Teste, a;
a = b->Z();
cout << "a->AnyNum: " << a->AnyNum << "\n";
b->Z(boost::shared_ptr<Teste>(new Teste));
cout << "a->AnyNum: " << a->AnyNum << "\n";
return 0;
}
Yes there is:
void Z(Teste *value)
{
value->AnyNum = 100;
*_Z = *value; // you need assignment operator
}
The compiler-generated assignment operator will not make a deep copy, instead it will make a shallow copy. What you have to do is to write a suitable assignment operator (and possibly a copy constructor) for Teste. Also, you don't have to check if a pointer is NULL before deleting it:
~Teste()
{
// no need for checking. Nothing will happen if you delete a NULL pointer
if (_Z != NULL)
DELETE(_Z);
}
You've got another problem: _Z is not an identifier you should be using. In general, it's best to avoid leading underscores, and in particular double underscores or underscores followed by a capital letter are reserved for the implementation.
What a mess!
The whole program is very hard to read because of the choice of identifier names to start with:
#ifndef DELETE
#define DELETE(var) delete var, var = NULL
#endif
I find that very ugly.
When using classes it seems very un-nessacery. You could use it where a variables is going out of scope but it is a waster of time in the destructor. I think it would be asier to wrap the code in some smart pointer:
class Teste
{
private:
Teste *_Z;
public:
Teste()
~Teste() // Delete the _Z pointer.
Teste *Z();
void Z(Teste *value);
};
Ok. You have a pointer member that you delete in the destructor.
This means you are taking ownership of the pointer. This means that the ule of four applies (similar to the rule of three but applicable to ownership rules). This means you basically need to write 4 methods or the compiler generated versions will mess up your code. The methods you should write are:
A Normal (or default constructor)
A Copy constructor
An Assignment operator
A destructor.
Your code only has two of these. You need to write the other two.
Or your object should not take ownership of the RAW pointer. ie. use a Smart Pointer.
Teste *_Z;
This is not allowed.
Identifiers beginning with an underscore and a capitol letter are reserved.
You run the risk of an OS macro messing up your code. Stop using an underscore as the first character of identifiers.
~Teste(){
if (_Z != NULL)
DELETE(_Z);
}
This is not needed. Asimple delete _Z would have been fine.
_Z is going out of scope because it is in the destructor so no need to set it to NULL.
The delete operator handles NULL pointers just fine.
~Test()
{ delete _Z;
}
Teste *Z(){
_Z = new Teste;
return _Z;
}
What happens if you call Z() multiple times (PS putting the * next to the Z rather than next to the Teste make it hard to read).
Each time you call Z() the member variable _Z is given a new value. But what happens to the old value? Basically you are leaking it. Also by returning a pointer to an object owned
inside Teste you are giving somebody else the opportunity to abuse the object (delete it etc). This is not good. There is no clear ownership indicated by this method.
Teste& Z()
{
delete _Z; // Destroy the old value
_Z = new Teste; // Allocate a new value.
return *_Z; // Return a reference. This indicates you are retaining ownership.
// Thus any user is not allowed to delete it.
// Also you should note in the docs that it is only valid
// until the next not const call on the object
}
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
You are copying the content of a newly constructed object (that contains a pointer) into another dynamically created object!
What happens if _Z had not been allocated first. The constructor sets it to NULL so there is no guarantee that it has a valid value.
Any object you allocate you should also delete. But here value is dynamically allocated passed into Z but never freed. The reason you get away with this is because the pointer is c
opied into _Z and _Z is deleted when its destructor is destroyed.
Teste *b = new Teste, *a;
That's really heard to read. Don;t be lazy write it out properly.
This is considered bad style and you would never get past any code review with that.
Teste* b = new Teste;
Teste* a; // Why not set it to NULL
a = b->Z();
Getting ab object for a. But who was destroying the object a or b?
b->Z(new Teste);
It just gets too convoluted after that.
(I tried to add this as a comment but that screws up the code..)
I'd aslo strongly suggest not to use
#ifndef DELETE
#define DELETE(var) delete var, var = NULL
#endif
but instead something like
struct Deleter
{
template< class tType >
void operator() ( tType*& p )
{
delete p;
p = 0;
}
};
usage:
Deleter()( somePointerToDeleteAndSetToZero );
(not really an answer, but a comment wouldn't do)
The way you defined your macro is prone to a subtle errors (and the fact that no one spotted it so far just proves it). Consider your code:
if (_Z != NULL) // yes, this check is not needed, but that's not the point I'm trying to make
DELETE(_Z);
What happens after the preprocessor pass:
if (_Z != 0)
delete _Z; _Z = 0;
If you still have trouble seeing it, let me indent it properly:
if (_Z != 0)
delete _Z;
_Z = 0;
It's not a big deal, given that particular if condition, but it will blow-up with anything else and you will spend ages trying to figure out why your pointers are suddenly NULL. That's why inline functions are preferred to macros - it's more difficult to mess them up.
Edit: ok, you used comma in your macro definition so you are safe... but I would still say it's safer to use [inline] function in this case. I'm not one of the do-not-use-macros-ever guys, but I wouldn't use them unless they are strictly necessary and they are not in this case
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
and
b->Z(new Teste);
creates a memory leak
the 'new Teste' never gets deleted, instead what you are doing is allocating a new object as parameter, then copying whatever is in there using *_Z = *value but the object is not deleted after the call.
if you were to write
Test* param - new Teste;
b->Z(param)
delete param;
it would be better
of course most would use boost::shared_ptr or something similar to avoid caring about delete and such
Related
This question already has answers here:
Why doesn't delete set the pointer to NULL?
(12 answers)
Why doesn't free(p) set p to NULL?
(9 answers)
Closed 5 years ago.
I have small piece of code:
#include <iostream>
using namespace std;
int main()
{
int *p = new int(10);
if(p != NULL)
{
cout<<"Deleted dynamic allocated memory"<<endl;
delete p;
}
if(p == NULL)
{
cout<<"NULL"<<endl;
}
else
{
cout<<"Not NULL"<<endl;
}
return 0;
}
After deleting dynamic allocated memory using delete operator, Why compilers do not assigned NULL to pointer(like p = NULL) automatically?
It would often be unnecessary, particularly in well-written code.
It could hide away bugs.
delete p; would be syntactically idiosyncratic if it modified its argument.
On (1) it would be particularly wasteful with std::unique_ptr.
In other words, burdening the programmer with this job if necessary is the right thing to do.
Because it is extra work (= more clock cycles, less performance), that is usually not needed.
If your design calls for NULLing a pointer to indicate that it no longer points at something useful, you can add code to do that. But that should not be the default, because it can be insufficient and pointless.
NULL pointers don't solve every possible problem:
int *ip = new int;
int *ip1 = ip;
delete ip;
if (ip1)
*ip1 = 3; // BOOM!
And they are often pointless:
struct s {
int *ip;
s() : ip(new int) {}
~s() { delete ip; } // nobody cares if ip is NULL, 'cause you can't see it
};
They are allowed to do so, but it isnt mandatory. I think the reason they dont do it consitently is because anyhow you cant rely on it. For example consider this:
int* a = new int(3);
int* b = a;
delete a;
/// ....
if (b != 0) { /// assume b is either null or points to something valid
std::cout << *b; /// ups
}
I have a question regarding how to correctly delete structs and it's respective pointers declared inside.
I have extracted an example from a project i have running and it doesn't seem to work correctly, the code doesn't crash but it seems i have some "memory leaks". I'm not sure that is the right wording. The issue is that the values is not really reset and are kept in the memory next time i initiate a class.
Sudocode below:
Header:
ProgramHeader.h
class ClassA : public publicClassA
{
public:
ClassA(void);
virtual ~ClassA();
private:
struct ApStruct{
struct
{
float *refA[2];
float *refB[2];
float *pVarA;
} fR;
struct
{
float *refA[2];
float *refB[2];
float *pVarA;
} f1kHz;
};
ApStruct* GetApStruct;
}
Program:
Program.cpp
#include "ProgramHeader.h"
ClassA::~ClassA()
{
//EDIT i did a typo my looks like this:
//delete ApStruct; //Wrong code
delete GetApStruct; //Corrected - however still not working
}
main()
{
GetApStruct = new ApStruct();
//Do Code
}
Hope it all makes a bit sense,
EDIT:
I have updated one wrong line in the code - however the question still remains the same. I will have a look at below to understand before i implement a solution.
EDIT 24/10/2015
I have been trying out a few of the suggestions below and im not able to find a solution to my issue, i must admit i also have difficulties to narrow it down what could cause it.
My code is part of a DLL. The code wraps some source code im not in control of, and therefore i have limited options how i init using constructors and new on pointers.
The reason i still think i have memory leak issues is if i add a "magic float" in my code the output of my functions change, even the float is not used anywhere - it is just declared.
I get different results when:
Calling InitCode - once!
then i will call CallCode multiple time - doing my calculations
Destruct the instance of the class
When i repeat the above again i get different result from the first time i run the code but afterwards it stays the same.
If i include the magic line all seems to work???
Updated SudoCode:
Program.cpp
#include "ProgramHeader.h"
ClassA::~ClassA()
{
//EDIT i did a typo my looks like this:
//delete ApStruct; //Wrong code
delete GetApStruct; //Corrected - however still not working
}
main()
{
void initCode()
{
GetApStruct = new ApStruct();
float InitValue = 0.F
//Magic line:
float magicLine = 123456.f; //If this line is commented out i get different results in my code
//End Magic Line
fr.refA[0] = &InitValue;
fr.refA[0] = &InitValue;
fr.refA[0] = &InitValue;
fr.pVarA = &InitValue;
...
}
void CallCode()
{
float CallValue = 123.F
//Magic line:
float magicLine = 123456.f; //If this line is commented out i get different results in my code
//End Magic Line
fr.refA[0] = &CallValue;
fr.refA[0] = &CallValue;
fr.refA[0] = &CallValue;
fr.pVarA = &CallValue;
...
}
}
Thanks guys for you support,
Thomas
I would recommend something like the following for allocation and cleanup...
#include <iostream>
using namespace std;
class ClassA
{
public:
ClassA(void);
virtual ~ClassA();
private:
struct ApStruct {
struct
{
float *refA[2];
float *refB[2];
float *pVarA;
} fR;
struct
{
float *refA[2];
float *refB[2];
float *pVarA;
} f1kHz;
};
ApStruct* GetApStruct;
};
ClassA::ClassA(void) {
GetApStruct = new ApStruct{};
GetApStruct->fR.refA[0] = new float{ 1.f };
GetApStruct->fR.refA[1] = new float{ 2.f };
GetApStruct->fR.refB[0] = new float{ 3.f };
GetApStruct->fR.refB[1] = new float{ 4.f };
GetApStruct->fR.pVarA = new float { 0.f };
// do same for struct f1kHz
// ...
cout << "Construction" << endl;
}
ClassA::~ClassA()
{
if (GetApStruct != nullptr) {
if (GetApStruct->fR.refA[0] != nullptr) {
delete GetApStruct->fR.refA[0];
GetApStruct->fR.refA[0] = nullptr;
}
if (GetApStruct->fR.refA[1] != nullptr) {
delete GetApStruct->fR.refA[1];
GetApStruct->fR.refA[1] = nullptr;
}
if (GetApStruct->fR.refB[0] != nullptr) {
delete GetApStruct->fR.refB[0];
GetApStruct->fR.refB[0] = nullptr;
}
if (GetApStruct->fR.refB[1] != nullptr) {
delete GetApStruct->fR.refB[1];
GetApStruct->fR.refB[1] = nullptr;
}
if (GetApStruct->fR.pVarA != nullptr) {
delete GetApStruct->fR.pVarA;
GetApStruct->fR.pVarA = nullptr;
}
// do same for struct f1kHz
// ...
// finally
delete GetApStruct;
GetApStruct = nullptr;
}
cout << "Destruction" << endl;
}
int main() {
{
ClassA a;
}
system("pause");
return 0;
}
Well when you create a structure/class object, it holds the variables and pointers in that object memory area( say an object occupies some space in memory. Let's call it a box). Those pointer variables when initialized with new() or malloc(), are given space outside of that box in which the object's data resides. Those pointers now point to some memory area that is outside of that object's memory area. Now when the object is destructed, that space occupied by object (as we called it the box) is destroyed accompanying the pointer variables. The memory area pointed by the pointers is still in there in program/process memory area. Now we have no clue what's it address or where it lies. That's called memory leak. To avoid this situation, we need to de-allocate the memory referenced by pointers using delete keyword. We're free to go now. I tried to illustrate it with a simple graphic below. ObjectA box illustrates the area occupied by it in the memory. Note that this container/box holds the local varialbes including pointer. The pointer points to some memory location, say 0xFFF... and is illustrated by green line. When we destroy ObjectA, It simply destroys everything in it including 0xFFF address. But the memory located on 0xFFF is still allocated in the memory. A memory leak.
In your destructor, de-allocate memory explicitly using delete keyword. Whoa! We saved the memory.
From Wikipedia Resource Acquisition Is Initialization
Resource Acquisition Is Initialization (RAII) is a programming idiom used prominently in C++. In RAII, resource acquisition is done during object creation, by the constructor, while resource release is done during object destruction, by the destructor. If objects are destroyed properly, resource leaks do not occur.
So you can new the memory used for pointers in constructor and release them in destructor:
ClassA::ClassA(void) {
GetApStruct = new ApStruct;
GetApStruct->fR.refA[0] = new float{ 1.f };
GetApStruct->fR.refA[1] = new float{ 2.f };
}
ClassA::~ClassA(void) {
delete []GetApStruct->fR.refA;
delete GetApStruct;
}
Alright, let me be direct:
If you are using new or delete, you are doing it wrong.
Unless you are an experienced user, or you wish to implement a low-level side project, do not ever use new and delete.
Instead, use the existing standard classes to handle memory ownership, and just avoid heap-allocation when it is unnecessary. As a bonus, not only will you avoid memory leaks, but you will also avoid dangling references (ie, using memory after deleting it).
class ClassA : public publicClassA {
public:
private:
struct ApStruct{
struct
{
float refA[2];
float refB[2];
float pVarA;
} fR;
struct
{
float refA[2];
float refB[2];
float pVarA;
} f1kHz;
};
ApStruct GetApStruct;
}
And yes, in your case it is as simple as removing the pointers. Otherwise, if you want dynamic arrays (ie, arrays whose length is unknown at compile-time) use std::vector.
Here's my problem. I've read many previous questions about how to delete a member of a list while iterating over it and I tried the various solutions that the answers proposed. It happens that they seem not to work. I have a list of classes of this kind:
class Walker {
public:
Walker(int);
~Walker();
double *x;
double *y;
double *z;
double weight;
int molteplicity;
};
The constructor and destructor are the following
Walker::Walker(int particle_num) {
x = new double[particle_num];
y = new double[particle_num];
z = new double[particle_num];
}
Walker::~Walker() {
delete x;
delete y;
delete z;
}
Now, the list
list<Walker> population;
is defined as a member of another class. Now, if the element molteplicity is null (calculated via another function) I have to dinamically remove the member from the class, and this is how I do it:
for( it = population.begin(); it != population.end(); ) {
if( it->molteplicity == 0 ) {
it = population.erase(it);
} else {
++it;
}
getting the following error at runtime:
prog(22332) malloc: * error for object 0x7f838ac03a60: pointer being
freed was not allocated
* set a breakpoint in malloc_error_break to debug Abort trap: 6
Do you see the error? Thank you very much for your help!! If you need some more code just let me know.
The problem has nothing to do with the use of std::list, but it's in the destructor:
Walker::~Walker() {
delete x;
delete y;
delete z;
}
You have allocated using new[], not new, therefore you have to use delete[] not delete:
Walker::~Walker() {
delete[] x;
delete[] y;
delete[] z;
}
Live demo
Notice also that molteplicity and weight are never initialized and can therefore contain any number (likely different from 0).
After those changes you program compiles and runs perfectly.
Also notice that new and delete are generally frowned upon in the C++ community for very good reasons. Use smart pointers or containers, and please, generally follow the rule of zero.
And finally you can reach a cleaner solution using std::list::remove_if. If you follow these tips, you'll get something along the lines of:
struct Walker {
Walker(int num)
: x(num), y(num), z(num)
, weight(0)
, molteplicity(0)
{}
std::vector<double> x, y, z;
double weight;
int molteplicity;
};
and used as:
std::list<Walker> population {...};
population.remove_if([](Walker const& w) { return w.molteplicity == 0; });
Live demo
Which is both more readable and more correct.
You should implement copy constructor, because the list uses it internally.
The copy must be done when you execute code like: list.push_back(Walker(5));. The temporary object must be moved or copied to the list.
Default copy constructor copies only pointers so destructor deallocate the same memory twice.
Also move semantic in this case is enought:
Please add this constructor to your code:
Walker(Walker&& other)
{
x = other.x;
y = other.y;
z = other.z;
weight = other.weight;
molteplicity = other.molteplicity;
//remove data from the original object to avoid freeing memory twice
other.x = nullptr;
other.y = nullptr;
other.z = nullptr;
}
and remove the copy constructor (or implement it properly):
Walker(const Walker& other) = delete;
If you use pointers and allocate memory then you should know the rule of three:
The rule of three (also known as the Law of The Big Three or The Big
Three) is a rule of thumb in C++ (prior to C++11) that claims that if
a class defines one of the following it should probably explicitly
define all three:
destructor
copy constructor
copy assignment operator
I have an object called a Chunk that holds a pointer to a b2Body. It does other important things, but i removed those for simplicity. Heads up, smart pointers won't work(I think), you'll see why.
class DChunk
{
public:
DChunk();
DChunk(const DChunk& old);
virtual ~DChunk();
virtual b2Body* getBody() const;
private:
b2Body* m_pBody;//pointer;
};
The question is, how to define when to delete the m_pBody object.
If I want to copy this object, like say there is a vector of these things and I push_back another, it will call the Copy Constructor, copy the memory address of m_pBody(thats what i want), and then delete the old one. If the Destructor on this object deletes m_pBody, that's obviously bad, because the new copy wont have a valid memory address, but if it doesn't delete it, then m_pBody will never be deleted, and it needs to be deleted when there are no more Chunks pointing at it.
The only correct way to delete the m_pBody object is to call m_pBody->GetWorld()->DestroyBody( m_pBody ); and thats not under my control, so smart pointers dont really work.
I was hoping there would be different types of destructors that get called appropriately, like when a copy has been made in a vector. Also, there should never be more than one Chunk associated with one b2Body, if that is helpful.
I will assume you have something like
vector<DChunck> myvec;
and you are worried about doing
obj=DChunk()
myvec.push_back(obj)
First of all (this is very beginner friendly approach, avoiding smart pointers or any C++11) there's something not quite correct about creating a container DChunk objects. That's because when you declare
vector<DChunk>
you are telling your vector that it will receive objects the size of DChunk.
However, since that class contains a pointer to an array, m_pBody (array's size will not be constant!), this approach will not be too "healthy" for C++.
Given this, you can do something else, sticking to your class design: create a container of pointers!
You can create
vector<DChunk*> myvec;
and if you want to add an object to that vector, you just do
DChunk *obj = new DChunk();
myvec.push_back(event);
since now the container is handling pointers, which can be juggled around without interfering with the objects content, avoiding the worries concerning a destructor.
Calling an object's method will now be, for example,
(*myvec[3]).getBody()
or (cleaner version)
myvec[3]->getBody()
Hope I addressed your question
You can also provide move constructor so that instead of copying, it would move stuff... Here's an example that I made some hours ago, because I had the same problem (I didn't know in what order would these constructors and when be called, also "&&" is move constructor):
A move constructor is similar to copy constructor. The difference is that in move constructor instead of copying values and stuff, you assign given object's pointers (not copy) and values to a new one (this->temp = OldClass.temp) and then make OldClass.temp = NULL; so that when the unavoidable destructor is called, it finds a NULL pointer and does not delete it.
#include <iostream>
#include <Windows.h>
class MyClass
{
public:
MyClass()
{
temp = new RECT();
ZeroMemory(temp, sizeof(RECT));
}
MyClass(int x, int y)
{
temp = new RECT();
ZeroMemory(temp, sizeof(RECT));
temp->left = x;
temp->top = y;
}
MyClass(MyClass &&OldClass)
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
temp = OldClass.temp;
OldClass.temp = NULL;
}
MyClass& operator=(MyClass &&OldClass)
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
temp = OldClass.temp;
OldClass.temp = NULL;
return *this;
}
MyClass(const MyClass &OldClass)
{
*temp = *OldClass.temp;
}
MyClass& operator=(const MyClass &OldClass)
{
*temp = *OldClass.temp;
return *this;
}
~MyClass()
{
if (this->temp != NULL)
{
delete this->temp;
this->temp = NULL;
}
}
void Print()
{
std::cout << temp << " " << temp->left << " " << temp->top << " " << temp->right << " " << temp->bottom << '\n';
}
private:
RECT *temp;
};
int main()
{
MyClass bla, cha(54, 48);
bla.Print();
cha.Print();
bla = MyClass(2, 2);
bla.Print();
bla = cha;
bla.Print();
cha = MyClass(54, 2);
cha.Print();
std::cin.get();
return 0;
}
In common, a proper memory management is non trivial task and no universal decision are existing. Some simple and common well-known methods are presented as "smart pointer" types in newest libraries (and you can also define them yourself (by copy known "standard definition")). But it also is not an completely universal :-)
And your question seems to be a question for a such universal solution.
Some other programming languages (java ... , not C++) advertise you to get rid of that problem (by the built-in methods of language implementations).
You write: "Also, there should never be more than one Chunk associated with one b2Body, if that is helpful." . And then the problem seems to disappear (because the Chunk cannot be copied at all). (?)
_transaction is a private member variable of my class, declared as:
public:
typedef stdext::hash_map<wchar_t*, MyClass*, ltstr> transaction_hash_map;
private:
transaction_hash_map _transactions;
During cleanup I am trying to iterate through this list and free up any objects still unfreed. However I am getting an AV on the for line here:
for (transaction_hash_map::const_iterator it = _transactions.begin(); it != _transactions.end(); it++)
{
MyClass* item = (MyClass*)it->second;
if (item != NULL)
{
item->End();
delete item;
}
}
Re: What is ltstr?
private:
struct ltstr
{
enum
{
bucket_size = 8,
min_buckets = 16
};
bool operator()(wchar_t* s1, wchar_t* s2) const
{
return wcscmp( s1, s2 ) < 0;
}
size_t operator()(wchar_t *s1) const
{
size_t h = 0;
wchar_t *p = const_cast<wchar_t*>(s1);
wchar_t zero = L'\0';
while ( *p != zero ) h = 31 * h + (*p++);
return h;
}
};
The stack shows it inside the begin() method. Any ideas?
One possible thing I can think of is that your class has already been deleted elsewhere before you try to iterate through the hash_map, and thus begin() will be operating on garbage. Worth a check...
Also - how are your wchar_t*'s getting allocated/freed? The code you've shown doesn't appear to be dealing with those. I'm not sure how that would cause trouble in your loop, but it's worth thinking about.
One minor thing - you shouldn't need the (MyClass*) cast. The hash_map's values should be of that type anyway, so it's nicer to let the compiler enforce type checks than to possibly bypass them with an explicit cast. That shouldn't be making any difference here though.
As I understand you're checking your pointer against NULL for the "remaining" items that might have not been deleted yet. But for the items you delete before your cleanup stage, do you set the pointer to NULL?
Notice that when you delete an object the pointer is not automatically set to NULL. So if you're not doing that you're trying to delete the same object twice (because your if statement will always be true), what could cause an access violation.
The code below is an example that causes a double deletion. It can be fixed if you uncomment the line that sets the pointer to NULL.
#include <cstddef>
struct Item {};
int main()
{
Item * p = new Item();
delete p;
//If you don't make the pointer null...
//p = NULL;
if (p != NULL)
//You delete the object twice.
delete p;
}
EDIT: I see you're getting the error exactly on the for line. So I'm wondering...
Apparently you have a MyClass that contains a _transactions member, which is a hash table with MyClass pointers as the data type. If the clean up code is performed inside a member function of MyClass, is it possible that you're deleting (for some reason) the MyClass instance that owns the _transactions you're iterating?
In this case you could get an error at it++ statement inside the for since the this object no longer exists. (Naturally, the error could be somewhere else too, like on the delete itself.)
Make sure to call _transactions.clear() after the for loop.