![]() | |
![]() |
| | Thread Tools | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
#3
| |||
| |||
|
#4
| ||||
| ||||
|
|
I guess my main point was that it is too easy to create code that looks perfectly valid (like my example), but had unintended side effects, due to the hidden nature of destructors being called as objects go out of scope. Here is an even simpler piece of code that runs into the same problem. int main(int argc,char **argv) { ResUse use; Connection con(....); Query q=con.query(); use=q.use("...."); } |
|
I don't know if the C++ standard prescribes the order in which destructors must be called when multiple objects go out of scope or not, but gcc anyway reasonably destructs them in the reverse order they were constructed in. |
|
In the above code 'con' gets destructed before 'use', which is a problem. Granted, if you understand the internals of mysql++, then you can see why this is a problem. But it's not entirely obvious to anyone else. After all, you can do without repercussions: {string A; string B; B="text"; A=B;} |
|
2) Make the default ctors for ResUse and Result private (which is not unlike there being no default ctors for Query and Connection) This would require making Query a friend of both classes. It would prevent you from compiling the problem code example above... and force you to create a ResUse from an existing object, thus in the proper order. Though it won't help in my original example where I explicitly called delete on the Connection. |
#5
| |||
| |||
|
|
1) If ResUse::~ResUse() didn't need to call conn_->unlock(), the problem would be solved. I admit I'm not familiar enough with the internals to know why it is needed and there probably is a very good reason, though I can't easily see what it is. I tried commenting it out and recompiling and running some of my programs with it and didn't run into problems. Nothing else calls unlock in result.cpp, and there's no guarantee when ResUse will be destructed, so it doesn't seem to be important for continuing onto the next transaction. But again, I'm probably missing something. |
#6
| |||
| |||
|
|
Overall, I believe this unlock() call is just a safety / sanity check. It should be removed. |
|
The only use of the lock mechanism in ResUse is to unlock. This goes against the idea that lock/unlock combos should be close together in the code, and always paired. I've removed it in SVN. |
#7
| ||||||
| ||||||
|
|
I guess my main point was that it is too easy to create code that looks perfectly valid (like my example), but had unintended side effects, due to the hidden nature of destructors being called as objects go out of scope. |
|
I don't know if the C++ standard prescribes the order in which destructors must be called |

|
1) If ResUse::~ResUse() didn't need to call conn_->unlock(), the problem would be solved. |
|
2) Make the default ctors for ResUse and Result private |
|
3) Add a note to the docs, warning about deleting Connection before things that depend on it go out of scope. |
|
Thanks for listening. |

![]() |
| Thread Tools | |
| Display Modes | |
| |