G
gw7rib
I've been bitten twice now by the same bug, and so I thought I would
draw it to people's attention to try to save others the problems I've
had. The bug arises when you copy code from a destructor to use
elsewhere.
For example, suppose you have a class Note. This class stores some
text, as a linked list of lines of text. The destructor runs as
follows:
Note::~Note() {
Line *lin, *lin2;
lin = firstline;
while (lin) {
lin2 = lin;
lin = lin -> next;
delete lin2; }
}
which works fine. You now decide it would be nice to be able to clear
the text of a note, using this code, so you split it up as follows:
Note::~Note() {
cleartext();
}
void Note::cleartext() {
Line *lin, *lin2;
lin = firstline;
while (lin) {
lin2 = lin;
lin = lin -> next;
delete lin2; }
}
So now you have an extra function you can use. And the destructor is
calling a neat, modular function, which is arguably better style than
the destructor being a sprawl of code.
The snag is that your program then mysteriously goes wrong. Worse
still, because the above is only a minor change to code that was
working perfectly, you tend to assume that the problem must instead lie
in the other changes you made at the same time - the code that uses
cleartext.
For those who haven't spotted the snag, the problem is this. The
destructor didn't try to leave the Note in a usable state, because the
Note was not going to be used again. Cleartext does however need to
leave the Note in a usable state, so it needs a line:
firstline = NULL;
to be added at the end. In fact, it also needs lastline = NULL; and a
few other additions.
Is this a bug that has been described before? If not, do I get to name
it? I was originally going to call it the "nicking code from the
destructor" bug but seeing as these newsgroups have an international
audience I think I will go for the "stealing code from the destructor"
bug. I've only hit the bug in C++ but presumably similar problems can
arise in any language that has some equivalent to a destructor.
draw it to people's attention to try to save others the problems I've
had. The bug arises when you copy code from a destructor to use
elsewhere.
For example, suppose you have a class Note. This class stores some
text, as a linked list of lines of text. The destructor runs as
follows:
Note::~Note() {
Line *lin, *lin2;
lin = firstline;
while (lin) {
lin2 = lin;
lin = lin -> next;
delete lin2; }
}
which works fine. You now decide it would be nice to be able to clear
the text of a note, using this code, so you split it up as follows:
Note::~Note() {
cleartext();
}
void Note::cleartext() {
Line *lin, *lin2;
lin = firstline;
while (lin) {
lin2 = lin;
lin = lin -> next;
delete lin2; }
}
So now you have an extra function you can use. And the destructor is
calling a neat, modular function, which is arguably better style than
the destructor being a sprawl of code.
The snag is that your program then mysteriously goes wrong. Worse
still, because the above is only a minor change to code that was
working perfectly, you tend to assume that the problem must instead lie
in the other changes you made at the same time - the code that uses
cleartext.
For those who haven't spotted the snag, the problem is this. The
destructor didn't try to leave the Note in a usable state, because the
Note was not going to be used again. Cleartext does however need to
leave the Note in a usable state, so it needs a line:
firstline = NULL;
to be added at the end. In fact, it also needs lastline = NULL; and a
few other additions.
Is this a bug that has been described before? If not, do I get to name
it? I was originally going to call it the "nicking code from the
destructor" bug but seeing as these newsgroups have an international
audience I think I will go for the "stealing code from the destructor"
bug. I've only hit the bug in C++ but presumably similar problems can
arise in any language that has some equivalent to a destructor.