Hi everyone,
The clang static analyzer gives a false positive warning on the following program:
$ cat falseLeak.cpp
struct CtrlBlk {
explicit CtrlBlk() : m_useCount(1) {}virtual void dispose();
void decUseCount() {
– m_useCount;
if (m_useCount == 0) { dispose(); }
}int m_useCount;
};struct Ptr {
Ptr() { m_cntrlBlk = new CtrlBlk; }
~Ptr() { m_cntrlBlk->decUseCount(); }
CtrlBlk* m_cntrlBlk;
};void testCase() { Ptr px; }
$ clang-tidy -checks=* falseLeak.cpp
1 warning generated.
/Users/benoit/tmp/falseLeak.cpp:20:27: warning: Potential leak of memory pointed to by ‘px.m_cntrlBlk’ [clang-analyzer-cplusplus.NewDeleteLeaks]
void testCase() { Ptr px; }
^
/Users/benoit/tmp/falseLeak.cpp:20:23: note: Calling default constructor for ‘Ptr’
void testCase() { Ptr px; }
^
/Users/benoit/tmp/falseLeak.cpp:15:26: note: Memory is allocated
Ptr() { m_cntrlBlk = new CtrlBlk; }
^
/Users/benoit/tmp/falseLeak.cpp:20:23: note: Returning from default constructor for ‘Ptr’
void testCase() { Ptr px; }
^
/Users/benoit/tmp/falseLeak.cpp:20:27: note: Potential leak of memory pointed to by ‘px.m_cntrlBlk’
void testCase() { Ptr px; }
^
Here’s my solution to silence up that false positive:
#ifdef clang_analyzer
/// \brief Escape a variable from the analysis of the clang static analyzer
///
/// This function takes a reference to a variable as an argument. This
/// causes the static analyzer tool to notice that the variable has escape
/// the scope of its analysis. It forces the static analyzer to make very
/// conservative assumptions about the state of the variable. This also
/// includes assumptions about any memory location referenced by this
/// variable.
///
/// This can be used to silence up false positives. In general, it is
/// better to augment the information available to the static analyzer
/// using attributes and/or assertions. Unfortunately, this isn’t always
/// possible. For example, it might be impossible to describe that a given
/// object is destructed along all execution paths.
template static void escapeFromClangStaticAnalysis(V& escapedVar);
#endifstruct CtrlBlk {
explicit CtrlBlk() : m_useCount(1) {}virtual void dispose();
void decUseCount() {
– m_useCount;
if (m_useCount == 0) { dispose(); }
#ifdef clang_analyzer
escapeFromClangStaticAnalysis(m_useCount);
#endif
}int m_useCount;
};struct Ptr {
Ptr() { m_cntrlBlk = new CtrlBlk; }
~Ptr() { m_cntrlBlk->decUseCount(); }
CtrlBlk* m_cntrlBlk;
};void testCase() { Ptr px; }
Would anyone have a better solution ?
Thanks,
Benoit
Benoit Belley
Sr Principal Developer
M&E-Product Development Group
MAIN +1 514 393 1616
DIRECT +1 438 448 6304
FAX +1 514 393 0110
Autodesk, Inc.
10 Duke Street
Montreal, Quebec, Canada H3C 2L7