Untitled

posted in Beals Software
Published July 23, 2009
Advertisement
I'm still here and I'm still working diligently, just not much to report. I've improved my toolbox a lot though:
Fixed a few bugs.Updated/improved some older code.Added an error system similar to Win32's Get/SetLastError().Went through and updated all of the code to utilize it the error system.Added support to de/serialize property bagsAdded a PropertyFile class (which is pretty much my "config file" class.)Added a DLL system.Fixed my ComPointer class (I think lol.)Fixed my assert macro.Added support for the performance counter (if available.)Added a Size3 math symbol and a couple more useful functions.


Adding the DLL system kind of threw things, because, as I said, I didn't want to include windows headers. I can get around this, but I don't know if it's legal to convert a FARPROC to a void pointer (or anything else for that matter) and back.

Another issue I'm not sure about is '__declspec(novtable)'. My understanding was that a class declared with it would not have a vtable, but my class still does (according to my compiler's watch window anyway.)

The only other issue is an...odd memory leak (reported by _CrtDumpMemoryLeaks().) I stripped my code down to just functions (none of which were being called) and the leak would show up SOMETIMES. I could comment out the code, run it, no memory leak. Uncomment the code, run it, no memory leak. Run it again, memory leak. A little confused really, plus the fact that defining _CRTDBG_MAP_ALLOC didn't change the output at all like it's supposed.

One other thing I'm not sure about is how to handle unloading my DLL files. At the moment I have a DllFile class and when it goes out of scope or I call Free(), the library is freed. My test bed code at the moment loads an interface from a DLL using a global DllFile, so when the app exits, the library is freed (which it would be anyway, via Win32), but this reports a memory leak and doesn't seem like the best way to handle it.

Any comments/suggestions?

[edit]
Guess I should add this because I've been asked by a couple friends. The toolbox (and all of my projects really) are very Windows oriented. Also, because of how I handle DLL exports, it's very MSVC++ oriented (because of the use of __FUNCTION__ and __FUNCDNAME__, and the linker pragma comment.)
Previous Entry Untitled
0 likes 3 comments

Comments

EDI
Maybe I'm wrong, but I see a lot of my influence in the code you've been writing in past journal posts; if so, good job :D
July 23, 2009 11:00 AM
Matias Goldberg
How do you load the DLLs?

Do you use LoadLibrary? Or do you use MSVC's linkage so the OS handles that for you?
Edit Oh I just saw you said you use the linker pragma. So it's the later one. Well, that means you don't have control of how DLLs are unloaded (unless someone here knows how to do that)

Sounds dumb but happens very often: Make sure CrtDumpMemoryLeaks is the LAST thing you call.
If you have singletons, the destructor will be called after returning main or WinMain. The same happens if you use static STL containers (even if you clear() them before returning from main).
Also it's probably that the DLLs are loaded and unloaded in different orders each time you run the test. So in some cases you call CrtDump before the dlls get unloaded, but doesn't mean you have a memory leak.

Also if you use multiple threads, take race conditions into account.

Example: The following code will report memory leaks when there aren't actually leaks:

static std::vector<int>  myVec;

int main( int nargs, char *argv[] )
{
	myVec.push_back( 1 );
	myVec.clear();

	_CrtDumpMemoryLeaks();

	return 0;
}




It will report memory leaks (at least it does for me) because delete [] is being called much long after returning from main, but it doesn't mean the memory doesn't actually get freed.

Also if you declare myVec inside main(), you'll see it still reports a leak. That's because the vector gets freed after going out of scope, but CrtDump is called inside that scope

Usually the best way I found to workaround this is to use a dummy Singleton that gets called as soon as main starts, so that it gets freed lasts and we are (almost) for sure we're in the end.

The following code workarounds this problem:

class DummySingleton
{
public:
	DummySingleton()
	{
	}
	~DummySingleton()
	{
		_CrtDumpMemoryLeaks();
	}

	void startDummy()
	{
	}
};

static DummySingleton myDummySingleton; //Make sure this gets declared FIRST
static std::vector<int>  myVec;

int main( int nargs, char *argv[] )
{
	myDummySingleton.startDummy(); //Call a FIRST function to init the singleton

	myVec.push_back( 1 );
	myVec.clear();

	return 0;
}





Try doing this and see if you still keep getting leaks. Any static variable or loading Dlls may be causing trouble because of the order they get loaded/unloaded

Hope this helps
Cheers
Dark Sylinc

Note: I don't like Singletons, I don't use them. But this is a special case that has nothing to do with code design patterns.
July 26, 2009 12:13 PM
Programmer16
@EDI:
What, it's not a good job if it's not influenced by you? [razz]
Now, I don't want to bloat your ego anymore (it's already hard enough to breath in here [razz]), but after all of the input and help you've given me, of course my code is influenced by yours. I haven't seen any of your recent stuff though, so a lot of it I've had to come up with on my own.

@Matias:
Thanks for the input, I really appreciate it!

The linker pragma is actually just for exporting the functions; I use LoadLibrary() and Co. to manage my DLLs. I've solved the load/free issue by implementing DLL manager functions into my kernel class. So, instead of:

dbtb::DllFile MyDll;
if(!MyDll.Load("SomeDll.dll"))
   return 0;
/* yada yada yada */
MyDll.Free();



I now have:

// MyKernel is an instance of my Kernel class
// The second parameter for LoadDll()
// tells the kernel if it is a required DLL.
DllHandle MyDll = MyKernel.LoadDll("SomeDll.dll", true);
if(MyDll)
{
    /* yada yada yada */
}
MyDll.Free(); // Not necessary, as soon as MyDll goes out of scope
// The library is freed.


The destructor for my Kernel class free's any DLL's loaded by the application and _CrtDumpMemoryLeaks() is called after I delete my kernel.

The scope issue is something that I was aware of; I tried to circumvent it with atexit(), but that didn't help. I hate to assume this, but I think it was a phantom leak or memory corruption from earlier in my coding session, because as soon as I restarted my computer, it disappeared completely. I'll keep the singleton idea in mind though, in case it comes up again; I'm not entirely sure when functions added with atexit() are called.
July 28, 2009 01:18 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement