Three days ago I discovered a bug in my programm, which was not so easy to find.
I often used a self defined class "AllocMemory" for allocating memory and all worked well.
So I wrote:
AllocMemory Allocation(length);
or also
AllocMemory Allocation = AllocMemory(length);
and following accesses e.g. via memcpy worked without problems.
But three days ago I had written:
1 2 3 4 5 6 7 8 9 10
|
AllocMemory Allocation
if(condition)
{
Allocation = AllocMemory(length);
...
memcopy(...,...,...);
....
}
....
| |
And the program hanged, when it reached memcpy.
So I thought I'am a newsbie with only half a year programming experience in C++ and 3 weeks in Visual Studio 2008 C++ and I don't know much about the finesses of programming in C++. And intuitively I corrected my mistake by writing:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
AllocMemory Allocation
if(condition)
{
AllocMemory TempAllocation(length);
Allocation = TempAllocation;
TempAllocation.DontFree(); // I had such a function
...
memcopy(...,...,...);
....
}
....
| |
And all worked well.
The day after, we had a holiday in Germany, and I was in an amusement park with family. But after some time I began to think about this programming problem. And what I thought then, was:
No it's not me who is the newbie. Maybe all others, who are programming in Visual Studio 2008 C++ are newbies. Most of them, because they don't know about the basics of Visual Studio 2008 C++ and some, because they don't know about programming generally in C++.
Yesterday I made some tests, and now I know exactly about the basics of programming in Visual Studio 2008 C++.
You know the basics of C++. So you know how instanciate an object:
It's this for example:
CatClass CatFrisky("Frisky");
or
CatClass CatTom = CatClass("Tom");
And I tested this and can tell you, that this not only works correct in normal C++, but also in this C++ of Microsoft.
Do you think, that operations like assignments work very different from normal C++. If you dont think so, then you are a newbie.
What do you think about:
MyCat = CatFrisky;
What will be the outcome, if you write such a line without knowing the basics?
The first Basic
Before you assign a new content to an existing object, you first have to destruct the old content.
|
Correct would be:
1 2
|
MyCat.~CatClass();
MyCat = CatFrisky;
| |
But if you think, not you are the newbie, but some others, you also can write:
1 2 3 4 5
|
// work around for:
// MyCat = CatFrisky;
MyCat.~CatClass(); // MS forgot this
MyCat = CatFrisky;
| |
The second basic is a very interesting one.
Do you know what happens, if you write:
CatClass("UnusedCat");
Don't worry, it also works correct with visual studio 2008. But it's important, that you know this.
What happens, is something like this:
1 2
|
CatClass * pTemp = new CatClass("UnusedCat");
delete pTemp;
| |
If you know this, can you imagine, what would happen, if you write the following, and why you shouldn't write it:
|
MyCat = CatClass("UsedCat");
| |
So please consider the second basic.
The second Basic
Consider the difference between an used and an unused object.
If you assign a new instanciated temporary object to an existing object, don't delete the temporary object, but only free the memory.
|
So instead of:
MyCat = CatClass("UsedCat");
write:
1 2 3 4 5 6 7
|
// Work around for:
// MyCat = CatClass("Frisky")
MyCat.~CatClass(); // MS forgot this
CatClass * pTemp = new CatClass("Frisky");
MyCat = * pTemp;
free(pTemp); // MS used delete
| |
It's a pity that you can't use this work around also for a function, which returns an object, like:
CatClass CatFrisky = ReturnCat("Frisky");
Oh, sorry for causing worries. No, no, this works well.
But I ment:
CatFrisky = ReturnCat("Frisky");
Do you wonder, how this problem could be solved? Then you should know about the third basic.
The third Basic
Use classes, which can disable destruction.
|
Istead of:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
class CatClass {
public:
char * Name;
CatClass(char * name = "UnnamedCat")
{
Name = name;
}
virtual ~CatClass()
{
Name = "DestructedCat";
}
};
| |
use:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
class CatClass {
private:
bool DestructionEnabled;
public:
char * Name;
CatClass(char * name = "UnnamedCat", bool destructenable = true)
{
Name = name;
DestructionEnabled = destructionenable;
}
void EnableDestruction()
{
DestructionEnabled = true;
}
virtual ~CatClass()
{
if(DestructionEnabled)
{
Name = "DestructedCat";
}
}
};
| |
Now it's not a problem to write the correct return function:
1 2 3 4 5 6
|
#define DONTDESTRUCT false
CatClass ReturnCat(char * name = "Unnamed Cat")
{
return CatClass(name,DONTDESTRUCT);
}
| |
And it's also easy now to write the correct work around:
1 2 3 4 5 6
|
// work around for:
// MyCat = ReturnCat("Frisky");
MyCat.~CatClass();
MyCat = ReturnCat("Frisky");
MyCat.EnableDestruction();
| |
Now you have much learned about programming in Visual 2008 C++ and you no longer are a newbie.
Maybe I helped you and now you also could help me?
My Question is:
Is there a bug fix for this behavior of the C++ compiler for Visual Studio 2008 Professional. It's only some months ago, when I installed this VS and there were a lot of updates, but seemingly no one which met my expectations.
Maybe this was fixed for Visuasl Studio 2010 or 2011. But we wouldn't like to buy new professional versions.
|
Thank you in advance
Your dadabe