D3DXCreateFont creates memory leak

Started by
9 comments, last by SiCrane 15 years, 8 months ago
The debug text from my Visual C++ compiler has this to say: The thread 'Win32 Thread' (0x1104) has exited with code 1 (0x1). The thread 'Win32 Thread' (0x15dc) has exited with code 1 (0x1). D3DX: MEMORY LEAKS DETECTED: 3 allocations unfreed (5572 bytes) D3DX: Set HKLM\Software\Microsoft\Direct3D\D3DXBreakOnAllocId=0x3e to debug The program '[4360] Run.exe: Native' has exited with code 1 (0x1). So I set D3DXBreakOnAllocId to 0x3e, and the compiler generated a break point after this function call: D3DXCreateFont( g_engine->GetPipeline()->GetDevice(), size, 0, FW_NORMAL, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, face, &m_font ); in this context:

Font::Font( int size, char* face, RECT box, DWORD flags, char* text )
{
	m_sprite = g_engine->GetPipeline()->GetSprite();

	D3DXCreateFont( g_engine->GetPipeline()->GetDevice(),
					size, 0,
					FW_NORMAL,
					1,
					FALSE,
					DEFAULT_CHARSET,
					OUT_DEFAULT_PRECIS,
					DEFAULT_QUALITY,
					DEFAULT_PITCH | FF_DONTCARE,
					face,
					&m_font );

	m_font->PreloadCharacters(32, 126);
	m_box = box;
	m_flags = flags;
	m_text = text;
}

Sure enough, if I don't create any fonts, I don't get the memory leak warning. Any ideas?
Advertisement
Are you sure you call Release() on the ID3DXFont interface?
Yes. Here is the .h file for the font class. Destructor releases m_font.

#ifndef FONT_H#define FONT_Hclass Font : public PipelineObject{public:	Font( int height, char* face, RECT box, DWORD flags, char* text = "" );	~Font()		 { SAFE_RELEASE(m_font); }	void SetFont( char* text );	void SetPosition( RECT box, DWORD flags = -1 );	void Render();private:	ID3DXFont* m_font;	ID3DXSprite* m_sprite;	char* m_text;	RECT m_box;	DWORD m_flags;};#endif

EDIT: Make source more readible
After playing around a little, I have noticed that the number of "allocations" unfreed is related to the number of characters I print, but there is no recognizable pattern. Changing the characters I preload also has a pattern-less impact. Setting ID3DXSprite to NULL in the DrawText method adds an additional 12 "allocations". I'm really not sure what's even causing this, but I think it's related to the individual glyphs being loaded and not unloaded?
This is just a shot in the dark, but is there any chance that you're releasing the device before the font gets released? (e.g., maybe you're releasing it manually?)

If so, I think this might cause some problems. I think the device should be the last thing that gets released, but like I said, I'm not sure.
You could be adding multiple references to the font object.
Release() returns an int which is the reference count, you could assert that it is 0.
If that is the problem, put the release in a while loop, or figure out why it is being addref'ed multiple times.
Quote:Original post by RabidDog
You could be adding multiple references to the font object.
Release() returns an int which is the reference count, you could assert that it is 0.
If that is the problem, put the release in a while loop, or figure out why it is being addref'ed multiple times.

I'm sorry, but I feel that is a very bad idea. While you did create the Font object, you don't have sole ownership over who takes a reference to it. If D3D or D3DX wants to hold a reference to the Font object, it is free to do so, so long as it releases it when it no longer needs it.

Back to TLAK1001's question,

I notice your font class has a base class. Is the destructor virtual? Better yet, set a breakpoint on your destructor and make sure it is being called.
Sirob Yes.» - status: Work-O-Rama.
You might also want to use CComPtr so that Release is called automatically for COM interfaces.I used it for all D3D objects and it works like a charm.
Quote:This is just a shot in the dark, but is there any chance that you're releasing the device before the font gets released?

Yes, this is the case. However, it is not the solution :D

Quote:Is the destructor virtual? Better yet, set a breakpoint on your destructor and make sure it is being called.

Ah, a brilliant point... It isn't! I'll change it and see what happens...
Hm, I figured it out. I have a pipeline class that holds a vector of base objects. The destructor calls m_objects.empty(); For whatever reason, the problem is solved by iterating through the vector and calling SAFE_DELETE() on each member. I thought vector::empty(); did this already, but apparently not...

Thanks all!

This topic is closed to new replies.

Advertisement