CRTP copy method warns of potential memory leak

I have a hierarchy of objects and should be able to clone objects from the base class. I followed a typical CRTP pattern, except that I also want to be able to return a child class if the copy is called directly from the child. To do this, I made the following sentence: https://stackoverflow.com/a/212960/

Everything seems to be fine, but Klang warns me that I have a potential memory leak. I reduced the code to this MCVE:

template <typename T> class CRTP { protected: virtual CRTP<T> *internal_copy(void) const { return new T(static_cast<const T&>(*this)); } public: T *copy(void) const { return static_cast<T*>(internal_copy()); } virtual ~CRTP(void) = default; }; class Impl : public CRTP<Impl> { }; int main(void) { Impl a; Impl *b = a.copy(); delete b; } 

As far as I can tell, there is no possible memory leak, but running Clang through Xcode shows this:

Clang potential memory leak

Is there a memory leak here? If not, what causes false positives and how can I get around it? (I would prefer not to disable static analysis)

+6
source share
2 answers

I found a workaround that makes the analyzer happy, while still allowing the use of this pattern. Just change the relationship between copy and internal_copy :

 template <typename T> class CRTP : public Base { protected: virtual CRTP<T> *internal_copy(void) const { return copy(); } public: T *copy(void) const { return new T(static_cast<const T&>(*this)); } }; 

This still works in the context of the original sentence here , because when copy allowed inside CRTP, it prefers canceling CRTP (although this is not a virtual method), so there is no endless loop.

As to why the analyzer is happy with this order, but not happy with the original order, I have no idea.

+1
source

I think the analyzer gets confused with static_cast in your copy method. If you just change it to dynamic_cast , it will no longer mark the line as a memory leak. This makes me think that he believes that you might put an instance of the base type ( CRTP<T> ) on its derived type ( T ), which, of course, will be invalid when dereferencing. Obviously, you are not doing this, so it could be a bug in the leak detector, or it could be something more subtle than what I'm thinking about. This may not be a mistake, but if Impl becomes more complex (e.g. with multiple inheritance), it can become a problem (like your static_cast in the copy-CTOR call).

This implementation (with fewer throws) also had zero leaks:

 template <typename T> class CRTP { protected: virtual T *internal_copy() const { return new T(static_cast<const T&>(*this)); } public: T *copy() const { return internal_copy(); } virtual ~CRTP() = default; }; 
+1
source

Source: https://habr.com/ru/post/1013071/


All Articles