Segfault with thread_local and std::unordered_map - c++

During a debugging session, I found a problem that I was able to reduce down to this C++11 code:
#include <thread>
#include <vector>
#include <unordered_map>
class MyClass
{
public:
MyClass(){
printf("%p\n", this);
}
~MyClass(){
printf("~%p\n", this);
}
std::unordered_map<int, int> member;
};
thread_local MyClass threadLocalObject;
int main(){
std::vector<std::thread> threads;
for (int i = 0; i < 40; ++i){
threads.emplace_back([&](){
printf("%ld\n", threadLocalObject.member.size());
});
}
for (auto &thread : threads)
thread.join();
return 0;
}
The compiler I use is g++-6 (Homebrew GCC 6.4.0) 6.4.0 on MacOS 10.12.6.
The problem is that it seems to crash inside the destructor of member.
It doesn't always crash, though, which makes me wonder if it's some kind of race condition between the threads.
Any help is appreciated, this drives me insane.
I had similar crashes with MinGW on Windows, so I really hope to gain some knowledge from someone who understands what is going on here.
This is one of the more drastic crashlogs of this code:
0x7f9b2ba00228
0x7f9b2ac02728
0x7f9b2ba004e8
0x7f9b2ae00128
0x7f9b2b800128
0x7f9b2ad00128
0x7f9b2ac025f8
0x7f9b2ad00178
0x7f9b2b900138
0x7f9b2b800288
0x7f9b2ad002d8
0x7f9b2b900188
0x7f9b2ba00388
0x7f9b2b800548
0x7f9b2b8003e8
0x7f9b2b800cd8
0x7f9b2af00898
0x7f9b2ba00a68
0x7f9b2ae00ad8
0x7f9b2af00c08
0x7f9b2b900918
0x7f9b2ba00dd8
0x7f9b2b801048
0x7f9b2ae00e48
0x7f9b2b8013b8
0x7f9b2b801728
0x7f9b2af00f78
0x7f9b2ba00538
0x7f9b2af012e8
0x7f9b2b9002e8
0x7f9b2af00268
0x7f9b2ae004a8
0x7f9b2b900338
0x7f9b2af003c8
0x7f9b2ae00608
0x7f9b2af00528
0x7f9b2ae00768
0x7f9b2ae008c8
0x7f9b2af00688
0x7f9b2af006d8
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
~0x7f9b2ba00228
0
0
0
0
0
0
0
0
0
0
0
0
~0x7f9b2ac025f8
~0x7f9b2ad00178
~0x7f9b2ad00128
a.out(32726,0x70000e123000) malloc: *** error for object 0xa38333130303962: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
~0x7f9b2b900138
~0x7f9b2ad002d8
a.out(32726,0x70000e2ac000) malloc: *** error for object 0xa38633830306561: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
~0x7f9b2ba00388
~0x7f9b2b800288
~0x7f9b2b800548
~0x7f9b2b8003e8
~0x7f9b2b800cd8
~0x7f9b2af00898
~0x7f9b2ba00a68
~0x7f9b2ae00ad8
~0x7f9b2af00c08
~0x7f9b2b900918
~0x7f9b2ba00dd8
~0x7f9b2ae00e48
~0x7f9b2b801048
~0x7f9b2b8013b8
~0x7f9b2b801728
~0x7f9b2af00f78
~0x7f9b2ba00538
~0x7f9b2af012e8
~0x7f9b2b9002e8
~0x7f9b2ae004a8
~0x7f9b2af00268
~0x7f9b2b900338
~0x7f9b2af003c8
~0x7f9b2ae00608
~0x7f9b2af00528
~0x7f9b2ae00768
~0x7f9b2ae008c8
~0x7f9b2af00688
~0x7f9b2af006d8
~0x7f9b2ac02728
~0x7f9b2ae00128
~0x7f9b2b800128
Illegal instruction: 4

Related

Load data from .ini crash my game! What can I do? c++

Hello I am trying to create a script to save/load my custom Weapon Layout for my game.
The save function works fine, but if I want load the layout, it crash my game.
I know where the problem is, but idk how to fix these, so I need your knowledge!
void SaveWeaponsLayout()
{
Ini wpLayout = (".\\Files\\Settings\\WeaponsLayout.ini");
Log::Msg("Reading Data for WeaponsLayout.ini!");
Player playerPed = PLAYER::PLAYER_PED_ID();
if (!ENTITY::IS_ENTITY_DEAD(playerPed))
{
for (auto & wpID : weaponLayoutList)
{
Hash weapon = wpID.weaponHash;
char * wpName = wpID.WeaponName;
if (WEAPON::HAS_PED_GOT_WEAPON(playerPed, wpID.weaponHash, 0))
{
int weaponInHex = weapon;
std::string weaponInHex_ = hexify< int >(weaponInHex);
wpLayout.WriteString(weaponInHex_, wpName, "WEAPONHASH");
}
for (auto & wpCompID : weaponComponentList)
{
Hash weaponComp = wpCompID.weaponCompHash;
char * wpCompName = wpCompID.weaponComponent;
if (WEAPON::HAS_PED_GOT_WEAPON_COMPONENT(playerPed, wpID.weaponHash, wpCompID.weaponCompHash))
{
int weaponCompInHex = weaponComp;
std::string weaponCompInHex_ = hexify< int >(weaponCompInHex);
wpLayout.WriteString(weaponCompInHex_, wpName, wpCompName);
}
}
}
}
Log::Msg("Files WeaponsLayout.ini created!");
Notifications::MessageCentre6000("~p~Saved~s~: Weapons Layout");
}
The list where I get the Weapon Data from the game >>
static struct wpList
{
__int64 weaponHash;
char * WeaponName;
};
static std::vector<wpList> weaponLayoutList{
//{ 0xA2719263, "Unarmed" },
{ 0xFBAB5776, "Parachute" },
{ 0x99B507EA, "Knife" },
{ 0x8BB05FD7, "Flashlight" },
{ 0xCD274149, "Battle Axe" },
{ 0x94117305, "Pool Cue" },
...
}; // 88x Weapons
The list where I get the Weapon Components Data from the game >>
static struct wpCompList
{
unsigned int weaponCompHash;
char * weaponComponent;
};
static std::vector<wpCompList> weaponComponentList{
{ 0x75414F30, "COMPONENT_AT_RAILCOVER_01" },
{ 0x0C164F53, "COMPONENT_AT_AR_AFGRIP" },
{ 0x359B7AAE, "COMPONENT_AT_PI_FLSH" },
{ 0x7BC4CDDC, "COMPONENT_AT_AR_FLSH" },
{ 0x9D2FBF29, "COMPONENT_AT_SCOPE_MACRO" },
...
}; // 551x Weapon Components
This is the WeaponsLayout.ini what I have saved!
[Micro SMG]
WEAPONHASH=0x13532244
COMPONENT_AT_PI_FLSH=0x359b7aae
COMPONENT_AT_AR_SUPP_02=0xa73d4664
COMPONENT_MICROSMG_CLIP_02=0x10e6ba2b
[Assault Rifle]
WEAPONHASH=0xbfefff6d
COMPONENT_ASSAULTRIFLE_CLIP_03=0xdbf0a53d
[Advanced Rifle]
WEAPONHASH=0xaf113f99
COMPONENT_AT_AR_FLSH=0x7bc4cddc
COMPONENT_ADVANCEDRIFLE_CLIP_01=0xfa8fa10f
[Pump Shotgun]
WEAPONHASH=0x1d073a89
COMPONENT_AT_AR_FLSH=0x7bc4cddc
COMPONENT_AT_SR_SUPP=0xe608b35e
COMPONENT_PUMPSHOTGUN_CLIP_01=0xd16f1438
COMPONENT_PUMPSHOTGUN_VARMOD_LOWRIDER=0xa2d79ddb
...so now my script what make me problems, because it search in my file for all Weapons & Weapon Components!
void LoadWeaponsLayout()
{
Log::Msg("Files reading WeaponsLayout.ini!");
Ini wpLayout = (".\\Files\\Settings\\WeaponsLayout.ini");
Player playerPed = PLAYER::PLAYER_PED_ID();
if (!ENTITY::IS_ENTITY_DEAD(playerPed))
{
for (auto wpID : weaponLayoutList)
{
char * wpName = wpID.WeaponName;
unsigned weaponX = wpLayout.GetInt(wpName, "WEAPONHASH");
if (!WEAPON::HAS_PED_GOT_WEAPON(playerPed, weaponX, 0))
{
WEAPON::GIVE_DELAYED_WEAPON_TO_PED(playerPed, weaponX, 9999, 0);
for (auto wpCompID : weaponComponentList)
{
char * wpCompoName = wpCompID.weaponComponent;
unsigned weaponComp = wpLayout.GetInt(wpName, wpCompoName);
WAIT(0);
if (WEAPON::DOES_WEAPON_TAKE_WEAPON_COMPONENT(weaponX, weaponComp))
{
WEAPON::GIVE_WEAPON_COMPONENT_TO_PED(playerPed, weaponX, weaponComp);
}
}
}
}
}
Log::Msg("Files WeaponsLayout.ini loaded!");
Notifications::MessageCentre4000("~p~Loaded~s~: Weapons Layout");
}
[my ini class]
class Ini
{
private:
std::string inifile;
public:
Ini(std::string file)
{
this->inifile = file;
}
void WriteString(std::string string, std::string app, std::string key)
{
WritePrivateProfileStringA(app.c_str(), key.c_str(), string.c_str(), this->inifile.c_str());
}
std::string GetString(std::string app, std::string key)
{
char buf[100];
GetPrivateProfileStringA(app.c_str(), key.c_str(), "NULL", buf, 100, this->inifile.c_str());
return (std::string)buf;
}
void WriteInt(int value, std::string app, std::string key)
{
WriteString(std::to_string(value), app, key);
}
int GetInt(std::string app, std::string key)
{
return std::stoi(GetString(app, key));
}
}
DEBUG:
Files reading WeaponsLayout.ini!
Exception thrown at 0x000007FEFD71A06D in GTA5.exe: Microsoft C++ exception: std::invalid_argument at memory location 0x000000013AD4E610.
The thread 0x4628 has exited with code 0 (0x0).
The thread 0x4d78 has exited with code 0 (0x0).
The thread 0x4cd0 has exited with code 0 (0x0).
The thread 0x3c20 has exited with code 0 (0x0).
The thread 0x3678 has exited with code 0 (0x0).
The thread 0x1278 has exited with code 0 (0x0).
The thread 0x59a0 has exited with code 0 (0x0).
The thread 0x5458 has exited with code 0 (0x0).
The thread 0x4a8c has exited with code 0 (0x0).
The thread 0x5300 has exited with code 0 (0x0).
The thread 0x4b20 has exited with code 0 (0x0).
The thread 0x526c has exited with code 0 (0x0).
The thread 0x500c has exited with code 0 (0x0).
The thread 0x4be0 has exited with code 0 (0x0).
The thread 0x266c has exited with code 0 (0x0).
The thread 0x59ec has exited with code 0 (0x0).
The thread 0x3020 has exited with code 0 (0x0).
The thread 0x581c has exited with code 0 (0x0).
The thread 0x5098 has exited with code 0 (0x0).
The thread 0xd98 has exited with code 0 (0x0).
The thread 0x5180 has exited with code 0 (0x0).
The thread 0x1cc8 has exited with code 0 (0x0).
The thread 0x4c84 has exited with code 0 (0x0).
The thread 0x112c has exited with code 0 (0x0).
The thread 0x2dc0 has exited with code 0 (0x0).
The thread 0x5910 has exited with code 0 (0x0).
The thread 0x59cc has exited with code 0 (0x0).
The thread 0x2eb4 has exited with code 0 (0x0).
The thread 0x5aec has exited with code 0 (0x0).
The thread 0x58cc has exited with code 0 (0x0).
The thread 0x5a94 has exited with code 0 (0x0).
The thread 0x481c has exited with code 0 (0x0).
The thread 0x5554 has exited with code 0 (0x0).
The thread 0x2358 has exited with code 0 (0x0).
The thread 0x1b70 has exited with code 0 (0x0).
The thread 0x5764 has exited with code 0 (0x0).
The thread 0x53cc has exited with code 0 (0x0).
The thread 0x4ba4 has exited with code 0 (0x0).
The thread 0x4008 has exited with code 0 (0x0).
The thread 0x566c has exited with code 0 (0x0).
The thread 0x415c has exited with code 0 (0x0).
The thread 0x4cc0 has exited with code 0 (0x0).
The thread 0x512c has exited with code 0 (0x0).
The thread 0x5614 has exited with code 0 (0x0).
The thread 0x5390 has exited with code 0 (0x0).
The thread 0x4d68 has exited with code 0 (0x0).
The thread 0x56e8 has exited with code 0 (0x0).
The thread 0x54e8 has exited with code 0 (0x0).
The thread 0x1bc0 has exited with code 0 (0x0).
The thread 0x55d0 has exited with code 0 (0x0).
The thread 0x4f1c has exited with code 0 (0x0).
The thread 0x4efc has exited with code 0 (0x0).
The thread 0x54b4 has exited with code 0 (0x0).
The thread 0x4144 has exited with code 0 (0x0).
The thread 0x614 has exited with code 0 (0x0).
The thread 0x5820 has exited with code 0 (0x0).
The thread 0x4878 has exited with code 0 (0x0).
The thread 0x4184 has exited with code 0 (0x0).
The thread 0x2064 has exited with code 0 (0x0).
The thread 0x568c has exited with code 0 (0x0).
The thread 0x30cc has exited with code 0 (0x0).
The thread 0x57d8 has exited with code 0 (0x0).
The thread 0x5658 has exited with code 0 (0x0).
The thread 0x4c94 has exited with code 0 (0x0).
The thread 0x5084 has exited with code 0 (0x0).
The thread 0x4ff4 has exited with code 0 (0x0).
The thread 0x5858 has exited with code 0 (0x0).
The thread 0x148c has exited with code 0 (0x0).
The thread 0x209c has exited with code 0 (0x0).
The thread 0x52bc has exited with code 0 (0x0).
The thread 0x5170 has exited with code 0 (0x0).
The thread 0x1388 has exited with code 0 (0x0).
The thread 0xc10 has exited with code 0 (0x0).
The thread 0x12c0 has exited with code 0 (0x0).
The thread 0xca8 has exited with code 0 (0x0).
The thread 0x2040 has exited with code 0 (0x0).
The thread 0x4d1c has exited with code 0 (0x0).
The thread 0x358c has exited with code 0 (0x0).
The thread 0x1eac has exited with code 0 (0x0).
The thread 0x5608 has exited with code 0 (0x0).
The thread 0x28d8 has exited with code 0 (0x0).
The thread 0x4c44 has exited with code 0 (0x0).
The thread 0x5a0c has exited with code 0 (0x0).
The thread 0x4420 has exited with code 0 (0x0).
The thread 0x5828 has exited with code 0 (0x0).
The thread 0x29f4 has exited with code 0 (0x0).
The thread 0x4e60 has exited with code 0 (0x0).
The thread 0x54c4 has exited with code 0 (0x0).
The thread 0x4564 has exited with code 0 (0x0).
The thread 0x50ec has exited with code 0 (0x0).
The thread 0x43cc has exited with code 0 (0x0).
The thread 0x4e74 has exited with code 0 (0x0).
The thread 0x549c has exited with code 0 (0x0).
The thread 0xd74 has exited with code 0 (0x0).
The thread 0x5b90 has exited with code 0 (0x0).
The thread 0x4f7c has exited with code 0 (0x0).
The thread 0x30e8 has exited with code 0 (0x0).
The thread 0x4f74 has exited with code 0 (0x0).
The thread 0x1530 has exited with code 0 (0x0).
The thread 0x5584 has exited with code 0 (0x0).
DXGI WARNING: Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live Producer at 0x0000000000474EA8, Refcount: 4. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live Object at 0x0000000000488880, Refcount: 4. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live Object at 0x00000000004640E0, Refcount: 1. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live Object : 2 [ STATE_CREATION WARNING #0: ]
The program '[22656] GTA5.exe' has exited with code 0 (0x0).

Thread Scheduler Error Visual Studio 2013 vs 2015

I recently upgraded some projects from VS2013 to VS2015 and I have found some problems with my threaded code. The issue seems to be that a thread that is waiting on a mutex to get unlocked is not getting control when another thread unlocks the mutex. Since the other thread is a loop that locks the mutex, does something, then unlocks it, the result is that thread running the loop many times and the other thread waiting >10sec for control. Below is a very small sample program that reproduces the bug for me.
#include "stdafx.h"
#include <thread>
#include <mutex>
#include <iostream>
std::mutex print_guard_;
int i = 0;
void RenderLoop()
{
while (true) {
print_guard_.lock();
std::cout << "Render: " << i << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
print_guard_.unlock();
std::this_thread::yield();
}
}
void Print()
{
print_guard_.lock();
std::cout << "Main Thread: " << i << std::endl;
print_guard_.unlock();
}
int main()
{
std::thread* thread_ = new std::thread(RenderLoop);
while (true) {
Print();
}
return 0;
}
The error occurs both with and without the yield command in the RenderLoop function. In Visual Studio 2015 I get something like:
Render: 0
Render: 0
Render: 0
Render: 0
Render: 0
Render: 0
Render: 0
Render: 0
Render: 0
... (continues for a few seconds or longer)
Main Thread: 0
Main Thread: 0
Main Thread: 0
Main Thread: 0
Main Thread: 0
Main Thread: 0
Render: 0
Render: 0
Render: 0
...
and on VS2013 I get
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Render: 0
Main Thread: 0
Anyone have any ideas on how to force the thread to give up control?

How to use DrMemory to display and report a memory leak in C++?

I am trying to use DrMemory as it seems to be an easy to use Windows Memory Leaking detection tool: http://www.drmemory.org/
I purposely created the c++ app below that might have a memory leak.
#include <iostream>
using namespace std;
class Dog{
public:
int a;
string b;
Dog()
{
a = 1;
b = "alfred";
}
~Dog()
{
}
};
class Example{
public:
Dog* d1;
Dog* d2;
string a;
int b;
Example()
{
a = "test";
b = 15;
d1 = new Dog();
d2 = new Dog();
}
~Example()
{
//delete d;
}
};
void createObjects(){
for(unsigned int i=0; i < 200; i++)
{
Dog* d = new Dog();
Example* b = new Example();
}
Dog* d = new Dog();
d = NULL;
Example* b = new Example();
b = NULL;
}
int main()
{
createObjects();
return 0;
}
After building this app along with the following options (as instructed by DrMemory documentation) "-ggdb -static-libgcc -static-libstdc++" , I executed the executable with drmemory.exe, like this:
drmemory.exe TestingDrMemory.exe
However, I am not seeing any error/log message related to the memory leak and I am unable to identify the line in the source code that this occurs. Is this possible in DrMemory? What is the correct way to use this in order to identify/detect lines in the source code that cause the memory leak?
The log is below:
Dr. Memory version 1.7.0 build 5 built on Apr 4 2014 23:38:05
Dr. Memory results for pid 18240: "TestingDrMemory.exe"
Application cmdline: "TestingDrMemory.exe"
Recorded 104 suppression(s) from default C:\Program Files (x86)\Dr. Memory\bin\suppress-default.txt
===========================================================================
FINAL SUMMARY:
DUPLICATE ERROR COUNTS:
SUPPRESSIONS USED:
NO ERRORS FOUND:
0 unique, 0 total unaddressable access(es)
0 unique, 0 total uninitialized access(es)
0 unique, 0 total invalid heap argument(s)
0 unique, 0 total GDI usage error(s)
0 unique, 0 total handle leak(s)
0 unique, 0 total warning(s)
0 unique, 0 total, 0 byte(s) of leak(s)
0 unique, 0 total, 0 byte(s) of possible leak(s)
0 unique, 0 total, 0 byte(s) of still-reachable allocation(s)
ERRORS IGNORED:
2 potential error(s) (suspected false positives)
(details: C:\Dr. Memory\DrMemory-TestingDrMemory.exe.18240.000\potential_errors.txt)
18 potential leak(s) (suspected false positives)
(details: C:\Dr. Memory\DrMemory-TestingDrMemory.exe.18240.000\potential_errors.txt)
Details: C:\Dr. Memory\DrMemory-TestingDrMemory.exe.18240.000\results.txt
From the drmemory.org
If your application links with a static library that was built with frame pointer optimizations and you observe missing frames on your callstacks, try running with the Dr. Memory runtime options -no_callstack_use_top_fp, -no_callstack_use_fp, and -callstack_conservative. These will add some additional overhead on malloc-intensive applications, but should eliminate skipped frames.
Try running drmem with -batch -no_callstack_use_fp -no_callstack_use_top_fp

Code::Blocks pthread example can not compile

Maybe this questions is easy but I can't figure it out how to resolve it:
I try to compile an example which has pthreas on windows 7 (64bit), with Code Blocks I downloaded the prebuild library and set up building_options: the path for the compiler pthreadLib\include and the linker to pthreadLib\lib\x64
The program is:
extern "C"
{
#include <pthread.h>
#include <unistd.h>
}
#include <iostream>
#include <windows.h>
using namespace std ;
void * function1(void * argument);
void * function2(void * argument);
int main( void )
{
pthread_t t1, t2 ; // declare 2 threads.
pthread_create( &t1, NULL, function1,NULL); // create a thread running function1
pthread_create( &t2, NULL, function2,NULL); // create a thread running function2
Sleep(1);
return 0;
}
void * function1(void * argument)
{
cout << " hello " << endl ;
Sleep(2); // fall alseep here for 2 seconds...
return 0;
}
void * function2(void * argument)
{
cout << " world " << endl ;
return 0;
}
In case I comment pthread_create(); function, than it builds. So pthread_t is recognized as a type.
When I try to compile with pthread_create I get an error:
mingw32-g++.exe -L..\libs\Pre-built.2\lib\x64 -LD:\DropBox\WorkUT\Programs\MyODP\libs -o bin\Release\RIP.exe obj\Release\main.o -s ..\libs\Pre-built.2\lib\x64\libpthreadGC2.a ..\libs\Pre-built.2\lib\x64\pthreadVC2.lib
obj\Release\main.o:main.cpp:(.text.startup+0x36): undefined reference to `_imp__pthread_create'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second(s))
1 error(s), 1 warning(s) (0 minute(s), 0 second(s))
Do I have to make additional setups in C::B? I tired to add the linker command -lpthread but is not recognized.
After 2 days I figured it out.
First: I installed the minGW 64 for Windows OS.
Next: I set up C::B to use the minGW_64 after this post.
Moreover: I added to the linker libs ..\libs\Pre-built.2\lib\x64\libpthreadGC2.a and ..\libs\Pre-built.2\lib\x64\pthreadVC2.lib. Finally, I added to my project the pthreadGC2.dll (64bit version!).
Lesson learned, don't mix lib. and compiler with 86 and 64.
For Linux
Use sleep(1) in stead of Sleep(1)

still reachable (false positive?) in custom exception

This is my first attempt to write a custom exception class implementing a simple form of stack-trace.
This is the .h:
class error {
public:
error ();
error (const error & err);
~error ();
int level ();
private:
int _level;
};
And this is the .cpp:
error::error ()
: _level (0) {}
error::error (const error & err)
: _level (err._level) {}
error::~error () {}
int error::level () {
return ++_level;
}
Then I define two macros, one to create an error and throw it the first time (INIT_ERROR), and the other to kick the catched errors (KICK_ERROR):
#define WHERE(stream) {fprintf (stream, " %-30s [%s: %3d]\n", __FUNCTION__, __FILE__, __LINE__);}
#define INIT_ERROR {fprintf (stderr, "# 0"); WHERE (stderr); throw error ();}
#define KICK_ERROR {fprintf (stderr, "# %2d", err.level ()); WHERE (stderr); throw;}
As you expect, the use is as follow:
if (something wrong)
INIT_ERROR;
for the first time, and:
try {
// some code
}
catch (error & err) {
KICK_ERROR;
}
for all the other times.
However, DrMemory (I'm working on Windows Xp), alert me about still reachable blocks:
ERRORS FOUND:
0 unique, 0 total unaddressable access(es)
0 unique, 0 total uninitialized access(es)
0 unique, 0 total invalid heap argument(s)
0 unique, 0 total GDI usage error(s)
0 unique, 0 total warning(s)
0 unique, 0 total, 0 byte(s) of leak(s)
0 unique, 0 total, 0 byte(s) of possible leak(s)
3 unique, 3 total, 16 byte(s) of still-reachable allocation(s)
ERRORS IGNORED:
3 potential leak(s) (suspected false positives)
For completeness, this is the main:
void fun3 () {
fprintf (stderr, "nothing special");
INIT_ERROR;
}
void fun2 () {
try {
fun3 ();
}
catch (error & err) {
KICK_ERROR;
}
}
void fun1 () {
try {
fun2 ();
}
catch (error & err) {
KICK_ERROR;
}
}
int main () {
try {
fun1 ();
}
catch (error & err) {
cerr << "error catched in main" << endl;
}
}
Is this something wrong in my code?
Suggestions?
Still reachable allocations are not leaks, this is memory that is still available to the program at exit. It might be allocated from the libraries you use. I would not worry about them.
I don't think that there are any leaks. Your code seems valid. I think that the three blocks are just the allocated objects that were still alive at the precise point of time when program was starting its cleanup-on-death, if you might call that so.
I mean, something trivial like, std::cout, your exception and some lingering temporary string ;)
If you'd like to verify that, add a top-level TRY/CATCH at the most outer scope od MAIN that calls your exception test, so that the exception will be actually caught, stack unwound and so that the program will exit normally. That way, after catch/unwind, the lingering exception object and other should be cleaned up and probalby you will see LESS still-reachables.
Not necessarily zero, that depends on libraries used and the way that "DrMemory" of yours account for CRT "baseline memory footprint", sorry I don't know how to call that better..