[Scummvm-devel] The Curious Case of NonCopyable

Matt matt at use.net
Tue Apr 28 23:19:25 CEST 2009

On Tue, 28 Apr 2009, Max Horn wrote:

>> However, the checks in these tools basically say it doesn't count.
>> This is
>> because the pointer member is in the subclass, which the NonCopyable
>> parent can't possibly know about and therefore handle the copy (deep
>> or
>> otherwise).
> Frankly I don't quite understand what you are saying here. So, those
> tools say something, fine -- yet I have seen tons of lint tools
> outputting spurious and incorrect warnings, so... What is the actual
> *issue* you perceive here? Can you give a code example that does
> something bad / wrong in an unexpected fashion?

First, let me remind that I know a thing or two about automated code 
analysis. Your tone implies (to me) I am blindly reading these things and 
parroting them without much though. This is not the case.

I did give an example where the protections could easily be circumvented 
by accident, and the compiler would not warn. You didn't quote that part; 
did you read it before you replied?

> In particular, trying to make a copy of a PluginManager does cause a
> compile time error (and the class is never to be subclassed, being a
> singleton). The only way I know of to defeat the purpose of
> NonCopyable is to make a subclass which provides its own explicit copy
> constructor / assignment operator -- well, if you try hard enough, you
> can always shoot into your own foot ;-).

The thing that makes theis error-prone is that the "attribute" of 
NonCopyable is three hops away in the inheritance hierarchy, in this case. 
That doesn't express the intention very well, and often leads to 
inadvertent mistakes, in my experience. Expressing the intention in the 
subclass reduces/eliminates this potential.

On top of all of this, this is just an inappropriate use of inheritance. 
The name "NonCopyable" implies a capability, which should be implemented 
as a pure interface. The copy ctor and assignment operator are not pure 
interfaces, for obvious reasons. As such, this stops being a "mix-in" 
style of multiply-inheriting different pure interfaces and sets an example 
for the classic multiple-inheritance anti-patterns that we all know are 
bad. Just in case the "bad" isn't clear: First, because this isn't a pure 
interface, we expect the subclasses to be a specialization of the 
NonCopyable base class -- they are not. Second, because of the multiple 
inheritance of concrete classes going on, if one of those other base 
classes does have these operators defined, any number of build/link issues 
could occur.

In short, it sets a bad example of C++ and OO programming for people who 
aren't deeply familiar with either or both. Part of mistake-proofing is 
making sure that if a part of the code will be used as an example or 
template, that it isn't propagating an anti-pattern.

I hope this is clear enough, now :)

> All in all, I am not convinced there is actually an issue, but then
> again, I am not sure I understood what your point is (it didn't come
> across from what you wrote, at least). So, I'll wait for some more
> explanations from you, resp. an example :-).

I provided an example in the original email, verbally. An example of 
another issue like this that is lying in wait is here:

--- Module:   gui\GuiManager.cpp (C++)
                                 _data = new byte[_size];
graphics\cursorman.h(181) : Info 1732: new in constructor for class 
     which has no assignment operator
graphics\cursorman.h(181) : Info 1733: new in constructor for class 
     which has no copy constructor
                         _data = new byte[_size];
graphics\cursorman.h(151) : Info 1732: new in constructor for class 
     which has no assignment operator
graphics\cursorman.h(151) : Info 1733: new in constructor for class 
     which has no copy constructor

Now, if this ever did result in a pointer aliasing issue at runtime, 
valgrind could find it. Assuming that you covered the codepath that 
exhibits the problem at runtime, which implies a high amount of code 
coverage that is repeatable and not time-intensive. In my experience, both 
runtime and static analysis tools need to be leveraged to get the best out 
of both.

Note that I am *not* just running the tool and bugging developers to 
eliminate warnings. I'm eliminating warnings myself, as it's something I 
can do in the small windows of time I have in my busy schedule. I have a 
lot of experience with this particular tool, and know how to balance its 
strengths and weaknesses. I fixed several other issues that had no 
ambiguity whatsoever; this issue, however, seemed to need more discussion 
to come to an agreed-upon solution.

Also note that this same issue is reported by G++ wth -Weffc++ and/or 
-Wextra. So, even if you have an allergic reaction to indepdendent code 
analysis tools, this is at least one place that an open source tool is in 
(correct) agreement with the proprietary tool.

I hope this helps! :)

tangled strands of DNA explain the way that I behave.

More information about the Scummvm-devel mailing list