Skip to content

Commit

Permalink
Adding tests for static initializers, and a fix that avoids false pos…
Browse files Browse the repository at this point in the history
…itives from C++ statics
  • Loading branch information
mattdurak committed Oct 16, 2020
1 parent 3d41e75 commit ffbbf00
Show file tree
Hide file tree
Showing 16 changed files with 712 additions and 47 deletions.
8 changes: 4 additions & 4 deletions setup/version.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

#define VLDVERSION L"2.5.5"
#define VERSION_NUMBER 2,5,5,0
#define VERSION_STRING "2.5.5.0"
#define VLDVERSION L"2.5.6"
#define VERSION_NUMBER 2,5,6,0
#define VERSION_STRING "2.5.6.0"
#define VERSION_COPYRIGHT "Copyright (C) 2005-2020"

#ifndef __FILE__
!define VLD_VERSION "2.5.5" // NSIS Script
!define VLD_VERSION "2.5.6" // NSIS Script
#endif
2 changes: 1 addition & 1 deletion setup/vld-setup.iss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Visual Leak Detector"
#define MyAppVersion "2.5.5"
#define MyAppVersion "2.5.6"
#define MyAppPublisher "VLD Team"
#define MyAppURL "http://vld.codeplex.com/"
#define MyAppRegKey "Software\Visual Leak Detector"
Expand Down
22 changes: 20 additions & 2 deletions src/callstack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,26 @@ UINT CallStack::isCrtStartupFunction( LPCWSTR functionName ) const
}

if (endWith(functionName, len, L"DllMainCRTStartup")
|| endWith(functionName, len, L"mainCRTStartup")
|| beginWith(functionName, len, L"`dynamic initializer for '")) {
|| endWith(functionName, len, L"mainCRTStartup")

// NOTE: This is tricky...
// This happens for c++ static initialization
// In some cases, we will see
// "namespace::`dynamic initializer for 'symbol'"
// In other cases, there is no namespace prepended, even if the symbol is in a namespace:
// "`dynamic initializer for 'namespace::symbol'"
// This happens above initterm in the stack, which means these statics can be ignored by the code above if they have the namespace

// Ideally, we would ignore dynamic initializers if we (somehow) know there is also a matching "`dynamic atexit destructor for 'symbol'"
// It's possible to use some kind of heuristic to detect this (the stack will have ..., classname::classname, dynamic initializer for, initterm, ...)
// That means that the caller really needs a state machine as we are doing some context-sensitive parsing

// For now, we just make the (possibly wrong) assumption that all dynamic initializations will be cleaned up
// Therefore, the following line is commented out.
// Clearly wrong when we have a global written as "static void* foo = malloc(1);"
// But we can look at a more complex fix if we need to handle that
//|| beginWith(functionName, len, L"`dynamic initializer for '")
) {
// When we reach this point there is no reason going further down the stack
return CALLSTACK_STATUS_NOTSTARTUPCRT;
}
Expand Down
4 changes: 4 additions & 0 deletions src/runtests.bat
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ ECHO ---------------------------------------------------------------------------
ECHO [ RUNNING ] %tests_path%\vld_main_test.exe
ECHO -------------------------------------------------------------------------------
!tests_path!\vld_main_test.exe --gtest_output="xml:!tests_path!\vld_main_test.exe.xml"
ECHO -------------------------------------------------------------------------------
ECHO [ RUNNING ] %tests_path%\static_string_test.exe
ECHO -------------------------------------------------------------------------------
!tests_path!\static_string_test.exe --gtest_output="xml:!tests_path!\static_string_test.exe.xml"
ECHO -------------------------------------------------------------------------------
EXIT /b 0

Expand Down
10 changes: 10 additions & 0 deletions src/tests/static_string_test/static_string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include <string>

namespace my_string
{
const std::string the_string("foobar");
}

const std::string string_global("xyz1234567");
35 changes: 35 additions & 0 deletions src/tests/static_string_test/static_string_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// static_string_test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "vld.h"
#include "static_string.h"

void access_strings()
{
// Just do something with the string so it isn't optimized away
std::string copied_string = my_string::the_string;
printf("Copied string %s\n", copied_string.c_str());

std::string copied_string2 = string_global;
printf("Copied string %s\n", copied_string2.c_str());
}

int main(int argc, char **argv)
{
access_strings();

int leaks = static_cast<int>(VLDGetLeaksCount());
if (0 != leaks)
{
printf("!!! FAILED - Leaks detected: %i\n", leaks);
VLDReportLeaks();
}
else
{
printf("PASSED\n");
}


return leaks;
}
Loading

0 comments on commit ffbbf00

Please sign in to comment.