Memory Leaks

Started by
11 comments, last by SiCrane 13 years, 4 months ago
I can not find where the memory leak is happening in my class (SkinnedMesh), I am releasing this:
SKINNEDMESH::~SKINNEDMESH(){	BONE_HIERARCHY boneHierarchy;	boneHierarchy.DestroyFrame(m_pRootBone);	if(m_pAnimControl)m_pAnimControl->Release();}
Advertisement
If you're sure the leak is due to the creation of a SKINNEDMESH instance, then either or both:

1. DestroyFrame is not deleting and releasing all objects that it should.

2. You create or new other objects in your SKINNEDMESH instance that aren't deleted or released in DestroyFrame (mesh, skininfo, textures, etc.).

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Quote:Original post by Buckeye
If you're sure the leak is due to the creation of a SKINNEDMESH instance, then either or both:

1. DestroyFrame is not deleting and releasing all objects that it should.

2. You create or new other objects in your SKINNEDMESH instance that aren't deleted or released in DestroyFrame (mesh, skininfo, textures, etc.).


Yes, I did the tests and the leak is in SkinnedMesh

I would ask for your help, because I have tried several ways and found where the leak is (something is going unnoticed by me)
my class:
#ifndef SKINNED_MESH#define SKINNED_MESH#include <windows.h>#include <d3dx9.h>#include <string>#include <vector>struct BONE: public D3DXFRAME{    D3DXMATRIX CombinedTransformationMatrix;};struct BONEMESH: public D3DXMESHCONTAINER{	ID3DXMesh* OriginalMesh;	std::vector<D3DMATERIAL9> materials;	std::vector<IDirect3DTexture9*> textures;	DWORD NumAttributeGroups;	D3DXATTRIBUTERANGE* attributeTable;	D3DXMATRIX** boneMatrixPtrs;	D3DXMATRIX* boneOffsetMatrices;	D3DXMATRIX* currentBoneMatrices;};class SKINNEDMESH{public:	SKINNEDMESH();	~SKINNEDMESH();	void Load(char *fileName, IDirect3DDevice9 *Dev);	void Render(BONE *bone, float scale);	void UpdateAnim(bool bones, D3DXMATRIX world, ID3DXAnimationController* animControl, float time);	void SetAnimation(char name[]);	void SetPosition(D3DXVECTOR3 pos);	void SetRotation(D3DXVECTOR3 angle);	std::vector<std::string> GetAnimations();	BONE* FindBone(char name[]);	//Controller of Bones	void mouselocal(D3DXVECTOR3 pos, int Width, D3DXMATRIX pm, D3DXMATRIX vm, D3DVIEWPORT9 vp); //Testesprivate:	void UpdateMatrices(bool bones, BONE* bone, D3DXMATRIX *parentMatrix);	void SetupBoneMatrixPointers(BONE *bone);	IDirect3DDevice9 *m_pDevice;	D3DXFRAME *m_pRootBone;	ID3DXAnimationController *m_pAnimControl;		D3DXVECTOR3 vPos;	D3DXVECTOR3 rotation;	float scale;	//Controller of Bones	D3DXVECTOR3 mouseLocation;	int m_Width;	D3DXMATRIX m_pm; // projection matrix	D3DXMATRIX m_vm; // view matrix	D3DVIEWPORT9 m_vp; // viewport};#endif


#include "skinnedMesh.h"class BONE_HIERARCHY: public ID3DXAllocateHierarchy{	public:		STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame);		STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR Name, CONST D3DXMESHDATA * pMeshData, CONST D3DXMATERIAL * pMaterials, CONST D3DXEFFECTINSTANCE * pEffectInstances, DWORD NumMaterials, CONST DWORD * pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER * ppNewMeshContainer);		STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);		STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);};HRESULT BONE_HIERARCHY::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame){	BONE *newBone = new BONE;	memset(newBone, 0, sizeof(BONE));	//Copy name	if(Name != NULL)	{		newBone->Name = new char[strlen(Name)+1];		strcpy(newBone->Name, Name);	}	//Set the transformation matrices	D3DXMatrixIdentity(&newBone->TransformationMatrix);	D3DXMatrixIdentity(&newBone->CombinedTransformationMatrix);	//Return the new bone...	*ppNewFrame = (D3DXFRAME*)newBone;	return S_OK;}HRESULT BONE_HIERARCHY::CreateMeshContainer(LPCSTR Name,											CONST D3DXMESHDATA *pMeshData,											CONST D3DXMATERIAL *pMaterials,											CONST D3DXEFFECTINSTANCE *pEffectInstances,											DWORD NumMaterials,											CONST DWORD *pAdjacency,											LPD3DXSKININFO pSkinInfo,											LPD3DXMESHCONTAINER *ppNewMeshContainer){	//Create new Bone Mesh	BONEMESH *boneMesh = new BONEMESH;	memset(boneMesh, 0, sizeof(BONEMESH));	//Get mesh data	boneMesh->OriginalMesh = pMeshData->pMesh;	boneMesh->MeshData.pMesh = pMeshData->pMesh;	boneMesh->MeshData.Type = pMeshData->Type;	pMeshData->pMesh->AddRef();		//Add Reference so that the mesh isnt deallocated	IDirect3DDevice9 *m_pDevice = NULL;		pMeshData->pMesh->GetDevice(&m_pDevice);	//Get m_pDevice ptr from mesh	//Copy materials and load textures (just like with a static mesh)	for(int i = 0; i < NumMaterials; i++)	{		D3DXMATERIAL mtrl;		memcpy(&mtrl, &pMaterials, sizeof(D3DXMATERIAL));		boneMesh->materials.push_back(mtrl.MatD3D);		char textureFname[200];		//strcpy(textureFname, "mesh/");		strcat(textureFname, mtrl.pTextureFilename);		//Load texture		IDirect3DTexture9* newTexture = NULL;		D3DXCreateTextureFromFile(m_pDevice, pMaterials.pTextureFilename, &newTexture);		boneMesh->textures.push_back(newTexture);	}	if(pSkinInfo != NULL)	{		//Get Skin Info		boneMesh->pSkinInfo = pSkinInfo;		pSkinInfo->AddRef();	//Add reference so that the SkinInfo isnt deallocated		//Clone mesh and store in boneMesh->MeshData.pMesh		pMeshData->pMesh->CloneMeshFVF(D3DXMESH_MANAGED, pMeshData->pMesh->GetFVF(), 									   m_pDevice, &boneMesh->MeshData.pMesh);				//Get Attribute Table		boneMesh->MeshData.pMesh->GetAttributeTable(NULL, &boneMesh->NumAttributeGroups);		boneMesh->attributeTable = new D3DXATTRIBUTERANGE[boneMesh->NumAttributeGroups];		boneMesh->MeshData.pMesh->GetAttributeTable(boneMesh->attributeTable, NULL);		//Create bone offset and current matrices		int NumBones = pSkinInfo->GetNumBones();		boneMesh->boneOffsetMatrices = new D3DXMATRIX[NumBones];				boneMesh->currentBoneMatrices = new D3DXMATRIX[NumBones];		//Get bone offset matrices		for(int i=0;i < NumBones;i++)			boneMesh->boneOffsetMatrices = *(boneMesh->pSkinInfo->GetBoneOffsetMatrix(i));	}	//Set ppNewMeshContainer to the newly created boneMesh container	*ppNewMeshContainer = boneMesh;	return S_OK;}HRESULT BONE_HIERARCHY::DestroyFrame(LPD3DXFRAME pFrameToFree) {	if(pFrameToFree)	{		//Free name		if(pFrameToFree->Name != NULL)			delete [] pFrameToFree->Name;		//Free bone		delete pFrameToFree;	}	pFrameToFree = NULL;    return S_OK; }HRESULT BONE_HIERARCHY::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase){	BONEMESH *boneMesh = (BONEMESH*)pMeshContainerBase;	//Release textures	for(int i=0;i < boneMesh->textures.size();i++)		if(boneMesh->textures != NULL)			boneMesh->textures->Release();	//Release mesh data	if(boneMesh->MeshData.pMesh)boneMesh->MeshData.pMesh->Release();	if(boneMesh->pSkinInfo)boneMesh->pSkinInfo->Release();	if(boneMesh->OriginalMesh)boneMesh->OriginalMesh->Release();	delete boneMesh;    return S_OK;}////////////////////////////////////////////////////////////////////////////////////////////////////									SKINNED MESH												////////////////////////////////////////////////////////////////////////////////////////////////////struct VERTEX{	VERTEX();	VERTEX(D3DXVECTOR3 pos, D3DCOLOR col){position = pos; color = col;}	D3DXVECTOR3 position;	D3DCOLOR color;	static const DWORD FVF;};const DWORD VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;SKINNEDMESH::SKINNEDMESH(){	m_pRootBone = NULL;	m_pAnimControl = NULL;	vPos=D3DXVECTOR3(0.0f,0.0f,0.0f);	rotation=D3DXVECTOR3(0.0f,0.0f,0.0f);	scale = 1;}SKINNEDMESH::~SKINNEDMESH(){	BONE_HIERARCHY boneHierarchy;	boneHierarchy.DestroyFrame(m_pRootBone);	if(m_pAnimControl)m_pAnimControl->Release();}void SKINNEDMESH::Load(char *fileName, IDirect3DDevice9 *Dev){	m_pDevice = Dev;	BONE_HIERARCHY boneHierarchy;	D3DXLoadMeshHierarchyFromX(fileName, D3DXMESH_MANAGED, 							   m_pDevice, &boneHierarchy,							   NULL, &m_pRootBone, &m_pAnimControl);	SetupBoneMatrixPointers((BONE*)m_pRootBone);	//Update all the bones	D3DXMATRIX i;	D3DXMatrixIdentity(&i);	UpdateMatrices(false, (BONE*)m_pRootBone, &i);}/*void SKINNEDMESH::UpdateMatrices(BONE* bone, D3DXMATRIX *parentMatrix){	if(bone == NULL)return;	D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,					   &bone->TransformationMatrix,					   parentMatrix);	if(bone->pFrameSibling)UpdateMatrices((BONE*)bone->pFrameSibling, parentMatrix);	if(bone->pFrameFirstChild)UpdateMatrices((BONE*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);}*/void SKINNEDMESH::UpdateMatrices(bool bones, BONE* bone, D3DXMATRIX *parentMatrix){	if(bones)	{		if(parentMatrix != NULL)		{			if(bone->Name != NULL && strcmp(bone->Name,"Bip01_L_UpperArm")==0) //|| strcmp(bone->Name,"Bip01_R_UpperArm")==0)			{				D3DXMATRIX ident;				D3DXMatrixIdentity(&ident);				D3DXMATRIX final = bone->TransformationMatrix*(*parentMatrix);				D3DXVECTOR3 boneLocation(final._41,final._42,final._43);				D3DXVec3Project(&boneLocation,&boneLocation,&m_vp,&m_pm,&m_vm,&ident); // use YOUR viewport, projection and view matrices in this call				D3DXVECTOR3 dir = mouseLocation - boneLocation;				if(mouseLocation.x > m_Width/2)				{					float offset = D3DX_PI/2.0f;					float angle = offset - atan2(dir.y,dir.x); // change this when you rotate the model					D3DXMATRIX rot;					D3DXMatrixRotationY(&rot,angle);					bone->CombinedTransformationMatrix = rot*final;				}				else				{					float offset = -D3DX_PI/2.0f;					float angle = offset + atan2(dir.y,dir.x); // change this when you rotate the model					D3DXMATRIX rot;					D3DXMatrixRotationY(&rot,angle);					bone->CombinedTransformationMatrix = rot*final;				}			}			else				D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,								   &bone->TransformationMatrix,								   parentMatrix);		}		else			bone->CombinedTransformationMatrix = bone->TransformationMatrix;		if(bone->pFrameSibling)		{			UpdateMatrices(bones, (BONE*)bone->pFrameSibling, parentMatrix);		}		if(bone->pFrameFirstChild)		{			UpdateMatrices(bones, (BONE*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);		}	}	else	{		if(bone != NULL)			D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,							   &bone->TransformationMatrix,							   parentMatrix);		else			bone->CombinedTransformationMatrix = bone->TransformationMatrix;		if(bone->pFrameSibling)			UpdateMatrices(bones, (BONE*)bone->pFrameSibling, parentMatrix);		if(bone->pFrameFirstChild)			UpdateMatrices(bones, (BONE*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);	}}void SKINNEDMESH::Render(BONE *bone, float scale){	if(bone == NULL)bone = (BONE*)m_pRootBone;	// Setup world matrix    D3DXMATRIXA16 matWorld,matWorld2;	// set the rotation matrix	D3DXMatrixRotationYawPitchRoll(&matWorld2,rotation.x,rotation.y,rotation.z);	D3DXMatrixScaling(&matWorld,scale,scale,scale);	D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);    D3DXMatrixTranslation( &matWorld2, vPos.x, vPos.y,vPos.z );	D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);    m_pDevice->SetTransform( D3DTS_WORLD, &matWorld );	//If there is a mesh to render...	if(bone->pMeshContainer != NULL)	{		BONEMESH *boneMesh = (BONEMESH*)bone->pMeshContainer;		if (boneMesh->pSkinInfo != NULL)		{					// set up bone transforms			int numBones = boneMesh->pSkinInfo->GetNumBones();			for(int i=0;i < numBones;i++)				D3DXMatrixMultiply(&boneMesh->currentBoneMatrices,								   &boneMesh->boneOffsetMatrices, 								   boneMesh->boneMatrixPtrs);			//Update the skinned mesh			BYTE *src = NULL, *dest = NULL;			boneMesh->OriginalMesh->LockVertexBuffer(D3DLOCK_READONLY, (VOID**)&src);			boneMesh->MeshData.pMesh->LockVertexBuffer(0, (VOID**)&dest);			boneMesh->pSkinInfo->UpdateSkinnedMesh(boneMesh->currentBoneMatrices, NULL, src, dest);			boneMesh->MeshData.pMesh->UnlockVertexBuffer();			boneMesh->OriginalMesh->UnlockVertexBuffer();			//Render the mesh			for(int i=0;i < boneMesh->NumAttributeGroups;i++)			{				int mtrlIndex = boneMesh->attributeTable.AttribId;				m_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));				m_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);				boneMesh->MeshData.pMesh->DrawSubset(mtrlIndex);			}		}	}	if(bone->pFrameSibling != NULL)Render((BONE*)bone->pFrameSibling, scale);	if(bone->pFrameFirstChild != NULL)Render((BONE*)bone->pFrameFirstChild, scale);}void SKINNEDMESH::SetupBoneMatrixPointers(BONE *bone){	if(bone->pMeshContainer != NULL)	{		BONEMESH *boneMesh = (BONEMESH*)bone->pMeshContainer;		if(boneMesh->pSkinInfo != NULL)		{			int NumBones = boneMesh->pSkinInfo->GetNumBones();			boneMesh->boneMatrixPtrs = new D3DXMATRIX*[NumBones];			for(int i=0;i < NumBones;i++)			{				BONE *b = (BONE*)D3DXFrameFind(m_pRootBone, boneMesh->pSkinInfo->GetBoneName(i));				if(b != NULL)boneMesh->boneMatrixPtrs = &b->CombinedTransformationMatrix;				else boneMesh->boneMatrixPtrs = NULL;			}		}	}	if(bone->pFrameSibling != NULL)SetupBoneMatrixPointers((BONE*)bone->pFrameSibling);	if(bone->pFrameFirstChild != NULL)SetupBoneMatrixPointers((BONE*)bone->pFrameFirstChild);}BONE* SKINNEDMESH::FindBone(char name[]){	return (BONE*) D3DXFrameFind(m_pRootBone, name);}void SKINNEDMESH::UpdateAnim(bool bones, D3DXMATRIX world, ID3DXAnimationController* animControl, float time){	if(animControl != NULL)		animControl->AdvanceTime(time, NULL);	else m_pAnimControl->AdvanceTime(time, NULL);	UpdateMatrices(bones, (BONE*)m_pRootBone, &world);}void SKINNEDMESH::SetAnimation(char name[]){	ID3DXAnimationSet *anim = NULL;	for(int i=0;i<m_pAnimControl->GetMaxNumAnimationSets();i++)	{		anim = NULL;		m_pAnimControl->GetAnimationSet(i, &anim);		if(anim != NULL)		{			if(strcmp(name, anim->GetName()) == 0)				m_pAnimControl->SetTrackAnimationSet(0, anim);			anim->Release();		}	}}std::vector<std::string> SKINNEDMESH::GetAnimations(){	ID3DXAnimationSet *anim = NULL;	std::vector<std::string> animations;	for(int i=0;i<m_pAnimControl->GetMaxNumAnimationSets();i++)	{		anim = NULL;		m_pAnimControl->GetAnimationSet(i, &anim);		if(anim != NULL)		{			animations.push_back(anim->GetName());			anim->Release();		}	}	return animations;}void SKINNEDMESH::SetPosition(D3DXVECTOR3 pos){	vPos = pos;}void SKINNEDMESH::SetRotation(D3DXVECTOR3 angle){	rotation = angle;}void SKINNEDMESH::mouselocal(D3DXVECTOR3 pos, int Width, D3DXMATRIX pm, D3DXMATRIX vm, D3DVIEWPORT9 vp){	mouseLocation = pos;	m_Width = Width;	m_pm = pm;	m_vm = vm;	m_vp = vp;}


Thank you
As mentioned above, DestroyFrame doesn't delete or release all the objects that were created. During the process of loading the mesh hierarchy, many objects (frames, meshes, materials, etc.) are created, and several DirectX objects are created that need to be released. Take a look at CreateFrame to see all the possibilities.

Your DestroyFrame(m_pRootBone) call merely deletes the memory allocated for the m_pRootBone frame, without deleting or releasing any of the objects that were created during the loading process.

You might try looking at the docs for D3DXFrameDestroy(..).

You can also google around for an example of using the AllocateHierchy implementation.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I tried something like this:

class BONE_HIERARCHY: public ID3DXAllocateHierarchy{	public:		STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame);		STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR Name, CONST D3DXMESHDATA * pMeshData, CONST D3DXMATERIAL * pMaterials, CONST D3DXEFFECTINSTANCE * pEffectInstances, DWORD NumMaterials, CONST DWORD * pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER * ppNewMeshContainer);		STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);		STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);		BONE_HIERARCHY(SKINNEDMESH *pSkinMesh) :  m_pSkinMesh(pSkinMesh) {} //here!this line is new!!public:	SKINNEDMESH* m_pSkinMesh; //my class of SkinnedMesh};


and
SKINNEDMESH::~SKINNEDMESH(){	BONE_HIERARCHY boneHierarchy(this);	boneHierarchy.DestroyFrame(m_pRootBone);	D3DXFrameDestroy(m_pRootBone, &boneHierarchy);	if(m_pAnimControl)		m_pAnimControl->Release();}


but when I close the game (which is the time that he tries to release the skinned mesh) compiler (debug) indicates a number of crashes and errors on the line D3DXFrameDestroy (m_pRootBone, & boneHierarchy)
Quote: (debug) indicates a number of crashes and errors on the line D3DXFrameDestroy (m_pRootBone, & boneHierarchy)

I would certainly expect that, since you destroy the root frame before you destroy the rest of the frames.
	boneHierarchy.DestroyFrame(m_pRootBone); // destroy the root frame	D3DXFrameDestroy(m_pRootBone, &boneHierarchy); // destroy a frame which has already been destroyed

I would strongly suggest you take a good look at your code and get a good understanding of what each piece does.

My previous post:
Quote:You can also google around for an example of using the AllocateHierchy implementation.

You really should do that.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I apologize, I need to deliver this work in college tomorrow, I will read more calmly on google :)

Thanks
I tried some examples and articles about D3DXFrameDestroy and followed them, the problem is that when he will release to this line:


SKINNEDMESH::~SKINNEDMESH(){	BONE_HIERARCHY boneHierarchy(this);	D3DXFrameDestroy(m_pRootBone, &boneHierarchy);	if(m_pAnimControl)		m_pAnimControl->Release();}

HRESULT BONE_HIERARCHY::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase){    UINT iMaterial;    BONEMESH *pMeshContainer = (BONEMESH*)pMeshContainerBase;	    SAFE_DELETE_ARRAY( pMeshContainer->Name );    SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency );    SAFE_DELETE_ARRAY( pMeshContainer->pMaterials );    SAFE_DELETE_ARRAY( pMeshContainer->boneOffsetMatrices );	    // release all the allocated textures	for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)    {            SAFE_RELEASE( pMeshContainer->textures[iMaterial] );    }		SAFE_DELETE_ARRAY( pMeshContainer->boneMatrixPtrs );    SAFE_RELEASE( pMeshContainer->MeshData.pMesh );    SAFE_RELEASE( pMeshContainer->pSkinInfo );    SAFE_RELEASE( pMeshContainer->OriginalMesh );    SAFE_DELETE( pMeshContainer );}HRESULT BONE_HIERARCHY::DestroyFrame(LPD3DXFRAME pFrameToFree) {    SAFE_DELETE_ARRAY( pFrameToFree->Name );    SAFE_DELETE( pFrameToFree );    return S_OK; }
Quote:the problem is that when he will release to this line

What's the problem?

Just a guess, but if it's a memory access violation, it may be that you don't initialize all the variables to 0 or NULL.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I think I'm doing it right
SKINNEDMESH::SKINNEDMESH(){	m_pRootBone = NULL;	m_pAnimControl = NULL;	vPos=D3DXVECTOR3(0.0f,0.0f,0.0f);	rotation=D3DXVECTOR3(0.0f,0.0f,0.0f);	scale = 1;}

This topic is closed to new replies.

Advertisement