Register Calendar Members List Administrators and Moderators Search Frequently Asked Questions Home

Game Coding Complete Programming Forum Win32 Programming DLL usage problem Hello Guest [login|register]
Last Post | First Unread Post Print Page | Recommend to Friend | Add Thread to Favorites
Post New ThreadPost Reply
Author
Post Previous Thread | Next Thread
GamerRick
Cool Newbie


Registration Date: 08-25-2005
Posts: 39
Location: Belmont CA

DLL usage problem Reply to this Post Post Reply with Quote Edit/Delete Post Report Post to a Moderator       IP Information Go to the top of this page

First of all, thank you Nebuchadnezzar for your help with my previous question. I got the Win32 Sys Prog 2nd book, and now have made the shared memory "volatile" and have create an event with the waitforsingleobject to control the thread. It works well.

I am having a new problem now. I want to create a DLL that has several common functions that DX programs will use. I added a function to it to load an Xfile, extract the textures and materials, add normals to the mesh, and optimize it.

My game runs fine until I exit. Then during the cleanup phase it bombs with an exception when it tries to delete the first class object that contains the first mesh. I traced it through the destructors. But it bombs in the dbgheap.c:

code:
#else  /* WINHEAP */

        /*
         * Go through the heap regions and see if the pointer lies within one
         * of the regions of the local heap.
         *
         * Pointers from non-local heaps cannot be handled. For example, a
         * non-local pointer may come from a DLL that has the CRT linked-in.
         *
         */

        for (i = 0; (base = _heap_regions[i]._regbase) != NULL &&
                i < _HEAP_REGIONMAX; i++)
        {
            if (pUserData >= base && pUserData <
                    (void *)(((char *)base)+_heap_regions[i]._currsize))
                return TRUE;
        }

        return FALSE;

#endif  /* WINHEAP */
--> } (THE GREEN POINTER IS HERE) 


If I put the exact same code in a function, instead of the DLL, I get no errors. So, it is only with the DLL function call that I get the problem.

What would be unique with the DLL memory management that could cause this? It seems to be a heap issue. I tried allocating memory for some strings with "new" instead of just as static in size, but no difference.

Oh, and I don't get any problems with the small test program I wrote to test/debug the DLL code. I only get it when I use the DLL in my game.

The second thread is not started until after the DLL has been used to create the meshes for the game.

Thanks.

10-17-2005 12:50 GamerRick is offline Search for Posts by GamerRick Add GamerRick to your Buddy List
GamerRick
Cool Newbie


Registration Date: 08-25-2005
Posts: 39
Location: Belmont CA

RE: DLL usage problem Reply to this Post Post Reply with Quote Edit/Delete Post Report Post to a Moderator       IP Information Go to the top of this page

I have attempted to trace it through every instruction being executed on the exit. It goes to the destructor of the derived class and executes the release of the textures, but there are no textures for that mesh, so it really does nothing. Then it hits the end of that destructor and I have a breakpoint at the beginning of the destructor in the base class, but it doesn't get there. It gets that error and stops there.

I am baffled. Baby

I have been reading all the books I have on memory management. No clue.

This post has been edited 1 time(s), it was last edited by GamerRick on 10-18-2005 at 20:28.

10-18-2005 20:25 GamerRick is offline Search for Posts by GamerRick Add GamerRick to your Buddy List
Nebuchadnezzar Nebuchadnezzar is a Male
Zealot




Registration Date: 03-12-2004
Posts: 203
Location: Las Vegas

Reply to this Post Post Reply with Quote Edit/Delete Post Report Post to a Moderator       IP Information Go to the top of this page

Does it do the same thing with a release build? You may be able to use an assert to catch the error - in other words, assert(test condition); prior to the call that causes the crash. Something odd might be happening.

Addionally, the problem might be that the memory being cleared isn't "local" to the dll. You might have to leave the cleanup to the main program instead of using common functions in the dll to do it. I don't usually fiddle much with dll's, so I'm not more than 50% sure of that....

Rich

__________________
"Your job is not to die for your country. Your job is to make some other poor sod die for his."

10-18-2005 23:33 Nebuchadnezzar is offline Send an Email to Nebuchadnezzar Homepage of Nebuchadnezzar Search for Posts by Nebuchadnezzar Add Nebuchadnezzar to your Buddy List
GamerRick
Cool Newbie


Registration Date: 08-25-2005
Posts: 39
Location: Belmont CA

Reply to this Post Post Reply with Quote Edit/Delete Post Report Post to a Moderator       IP Information Go to the top of this page

The DLL is only used during initialization to load the xfiles. I have a class (called XFileObject) that contains the resulting mesh and all associated stuff (materials, textures, etc). So, I don't know why the DLL would cause the problem at exit time.

code:
#define EXPORT __declspec (dllexport)

EXPORT HRESULT CALLBACK DXLoadXfile(IDirect3DDevice9* pDevice, 
LPWSTR Xfn,
std::vector<D3DMATERIAL9>& XFMtrls, 
std::vector<IDirect3DTexture9*>& XFTextures,
ID3DXMesh** ppObjectMesh,
UINT OPTIONS)
{
HRESULT hr;
ID3DXMesh* ObjectMesh = NULL;
const UINT TpathL  = 259;
const UINT UFnL    = 100;
TCHAR Tpath[260];
TCHAR UFn[200];
TCHAR CurrPath[260];

DWORD CPL = GetCurrentDirectory(259, CurrPath); // save current directory
if (CPL == NULL)
return E_FAIL;

size_t FnLength;

ID3DXBuffer* adjBuffer = 0;        // buffer for adjacency info
ID3DXBuffer* mtrlBuffer = 0;       // buffer for materials
DWORD numMtrls = 0;

hr = D3DXLoadMeshFromX( 
Xfn, // Xfile to load
D3DXMESH_MANAGED,
pDevice,
&adjBuffer,                    // Pointer to adjacency buffer
&mtrlBuffer,                   // Pointer to material buffer
0,                             // effect instances (unused)
&numMtrls,                     // Number of materials
&ObjectMesh);    // ID3DXMesh

if (FAILED(hr))
return hr;

if ((OPTIONS & OPT_TEXSAMEASX) != 0) // Use path from xfile
{
hr = StringCchLength(Xfn, TpathL, &FnLength);
if (FAILED(hr))
return hr;

// Save path of xfile to use for textures
hr = StringCchCopy(Tpath, FnLength + 1, Xfn);
if (FAILED(hr))
return hr;

size_t pos;
for ( pos = FnLength; pos > 0; pos-- )
{
if (Tpath[pos] == '\\')
break;
}

if (pos > 0)
Tpath[pos+1] = NULL;
else
Tpath[0] = NULL; // there is no path

SetCurrentDirectory(Tpath);
}

ID3DXBuffer* errors = 0;
DWORD* Tadj = static_cast<DWORD*>(adjBuffer->GetBufferPointer());

hr = D3DXValidMesh(ObjectMesh, (DWORD*) adjBuffer->GetBufferPointer(), &errors);
SAFE_RELEASE(errors);
ID3DXMesh* TMesh = NULL;

if (FAILED(hr))
{
try
{
if (hr == D3DXERR_INVALIDMESH)
{
hr = D3DXCleanMesh(D3DXCLEAN_SIMPLIFICATION,
ObjectMesh, Tadj, &TMesh, 
Tadj,
&errors);

if( errors )
{
MessageBoxA(0, (char*)errors->GetBufferPointer(), 0, 0);
throw hr;
}
if (FAILED(hr))
{
MessageBox(0, L"D3DXCleanMesh - Failed", L"ERROR", 0);
throw hr;
}

ObjectMesh->Release();
ObjectMesh = TMesh;
TMesh = NULL;

}
else
throw hr;
}
catch (HRESULT hr)
{
SAFE_RELEASE(errors);
SAFE_RELEASE(adjBuffer);
SAFE_RELEASE(ObjectMesh);
SAFE_RELEASE(TMesh);
return hr;
}
}

try
{
if( mtrlBuffer != 0 && numMtrls != 0 )
{
D3DXMATERIAL* mtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();

for(DWORD i = 0; i < numMtrls; i++)
{
// the MatD3D property doesn't have an ambient value set
// when its loaded, so set it now:
mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse;
        
// save the ith material

XFMtrls.push_back( mtrls[i].MatD3D );
        
// check if the ith material has an associative texture

if( mtrls[i].pTextureFilename != NULL )
{
size_t cc;
hr = StringCchLengthA(mtrls[i].pTextureFilename, UFnL, &cc);
if (FAILED(hr))
throw E_FAIL;

//size_t cc = mbstowcs(UFn, mtrls[i].pTextureFilename, 99);  // convert char* string to UNICODE
int MBL = MultiByteToWideChar(CP_ACP, NULL, mtrls[i].pTextureFilename, int(cc+1),
UFn, UFnL);
if (MBL <= 0 || MBL > UFnL)
throw E_FAIL;

if ((OPTIONS & OPT_TEXSAMEASX) != 0) // Use path from xfile
{
size_t pos = MBL;
TCHAR* pUFn = UFn+MBL; // point to end of file name
while ( pos > 0 && *pUFn != TCHAR('\\'))
{
pos--;
pUFn--;
}

hr = StringCchCopy(Tpath, TpathL, pUFn);
if (FAILED(hr))
throw hr;
}
else // use path and file name from Xfile
{
hr = StringCchCopy(Tpath, TpathL, UFn);
if (FAILED(hr))
throw hr;
}

IDirect3DTexture9* tex = 0;
hr = D3DXCreateTextureFromFile(pDevice,
Tpath,
&tex);

if (FAILED(hr))
throw hr;
            
// save the loaded texture
XFTextures.push_back( tex );
}
else
{
// no texture for the ith subset
XFTextures.push_back( NULL );
}
} // end for
} // End if materials
}
catch (HRESULT hr)
{
SAFE_RELEASE(mtrlBuffer);
SAFE_RELEASE(adjBuffer);
SAFE_RELEASE(ObjectMesh);
for(UINT i = 0; i < XFTextures.size(); i++)
SAFE_RELEASE(XFTextures[i]);
XFTextures.clear();
XFMtrls.clear();
return hr;
}

SAFE_RELEASE(mtrlBuffer); // done w/ buffer

if ((OPTIONS & OPT_GENNORMALS) != 0)
{
D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
bool hasNormals = false;
hr = ObjectMesh->GetDeclaration(elems);
if (SUCCEEDED(hr))
{
for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
{
// Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}?
if(elems[i].Stream == 0xff)
break;

if( elems[i].Type == D3DDECLTYPE_FLOAT3 &&
elems[i].Usage == D3DDECLUSAGE_NORMAL &&
elems[i].UsageIndex == 0 )
{
hasNormals = true;
break;
}
}
}
else
{
DWORD meshFVF = ObjectMesh->GetFVF();
if ((meshFVF & D3DFVF_NORMAL) == 0)
hasNormals = false;
}

ID3DXMesh* tempMesh = 0;

try
{
if (!hasNormals)
{
hr = ObjectMesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX2 ,
pDevice, &tempMesh);
if (FAILED(hr))
throw hr;

hr = D3DXComputeNormals(tempMesh, 0);
if (FAILED(hr))
throw hr;

SAFE_RELEASE(ObjectMesh);

ObjectMesh = tempMesh;
tempMesh = NULL;

hr = ObjectMesh->GenerateAdjacency(0.001f, Tadj);
if (SUCCEEDED(hr))
{
hr = ObjectMesh->OptimizeInplace( 
D3DXMESHOPT_ATTRSORT |
D3DXMESHOPT_COMPACT |
D3DXMESHOPT_VERTEXCACHE,
Tadj,
0, 0, 0);
}
if (FAILED(hr))
throw hr;
}
else
{
hr = ObjectMesh->OptimizeInplace( 
D3DXMESHOPT_ATTRSORT |
D3DXMESHOPT_COMPACT |
D3DXMESHOPT_VERTEXCACHE,
Tadj,
0, 0, 0);
if (FAILED(hr))
throw hr;
}
}
catch (HRESULT hr)
{
SAFE_RELEASE(adjBuffer);
SAFE_RELEASE(ObjectMesh);
SAFE_RELEASE(tempMesh);
for(UINT i = 0; i < XFTextures.size(); i++)
SAFE_RELEASE(XFTextures[i]);
XFTextures.clear();
XFMtrls.clear();
return hr;
}
}

SAFE_RELEASE(adjBuffer);

*ppObjectMesh = ObjectMesh;
SetCurrentDirectory(CurrPath);
return hr;
}

10-19-2005 13:27 GamerRick is offline Search for Posts by GamerRick Add GamerRick to your Buddy List
Tree Structure | Board Structure
Post New Thread Post Reply
Go to:

Powered by Berning Bored 3.1.4 2007
Content Copyright 2002-2009 (C) by Mike McShaffry