Discussion:
Excessive "fd" bytes at its tail of heap allocation
(too old to reply)
Jack
2009-12-18 10:10:19 UTC
Permalink
Hi guys,
When I run my application with the following
coding, it suffers from memory leaks of 4 bytes of
about 10-20 chunks...

[code]
__int64 FileSize64( const char * szFileName )
{
struct __stat64 fileStat;
int err = _stat64( szFileName, &fileStat );
if (0 != err) return 0;
return fileStat.st_size;
}

HRESULT LoadMesh(const char *szfilename)
{
PBYTE pMappedFileBase = NULL;

FILE *fp = fopen (szPath, "rb");
if (fp == NULL)
OutputDebugStringA("File open error\n");
__int64 si = FileSize64(szPath);

int actlen = si-4;

// I have tried using the std::vector<BYTE> v(len) technique,
// but I've got the same results.
pMappedFileBase = new BYTE[actlen];

memset (pMappedFileBase, 0, actlen);
..
if (pMappedFileBase)
{
delete[] pMappedFileBase;
pMappedFileBase = NULL;
}
[/code]

It is similar to the eariler case I posted in here,
as it suffered from memory leaks as well.

00 00 00 00 00 00 00....
fd fd fd fd

I've checked many places including the opened file itself and the stack..
When I don't use si-4 for actlen, but si, the fd bytes
were shifted down for another 4 bytes
like this,
00 00..
00 00 00 00 fd fd fd fd

I am totally exhausted because this problem has baffled me for 2 days for
many hours...so please help!
Thanks and again
Jack
Jack
2009-12-18 10:19:27 UTC
Permalink
Post by Jack
HRESULT LoadMesh(const char *szfilename)
{
PBYTE pMappedFileBase = NULL;
FILE *fp = fopen (szPath, "rb");
if (fp == NULL)
OutputDebugStringA("File open error\n");
__int64 si = FileSize64(szPath);
int actlen = si-4;
// I have tried using the std::vector<BYTE> v(len) technique,
// but I've got the same results.
pMappedFileBase = new BYTE[actlen];
memset (pMappedFileBase, 0, actlen);
Breakpoint here where I discovered the excessive "fd"
bytes.
Post by Jack
..
if (pMappedFileBase)
{
delete[] pMappedFileBase;
pMappedFileBase = NULL;
}
[/code]
It is similar to the eariler case I posted in here,
as it suffered from memory leaks as well.
00 00 00 00 00 00 00....
fd fd fd fd
I've checked many places including the opened file itself and the stack..
When I don't use si-4 for actlen, but si, the fd bytes
were shifted down for another 4 bytes
like this,
00 00..
00 00 00 00 fd fd fd fd
I am totally exhausted because this problem has baffled me for 2 days for
many hours...so please help!
Thanks and again
Jack
Igor Tandetnik
2009-12-18 12:49:58 UTC
Permalink
Post by Jack
It is similar to the eariler case I posted in here,
as it suffered from memory leaks as well.
There's nothing wrong in the code you showed. The problem must be in the code you didn't show.
Post by Jack
00 00 00 00 00 00 00....
fd fd fd fd
I've checked many places including the opened file itself and the stack..
This is normal. In a debug build, when you allocate memory, the actual allocation is slightly larger than what you asked for, and the block is filled with FD pattern. This serves two purposes: a) when you deallocate this block, the code in debug library checks that the extra allocated memory is still filled with FD pattern: if it's not, it knows you've overrun the buffer, and asserts; and b) while debugging, if you see, say, a field in a structure filled with FD pattern, it's a good indication that you forgot to initialize it.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Jack
2009-12-18 13:24:00 UTC
Permalink
Hi Igor,
Thanks for your help!
here is the entire method.. pls take a look
With a couple of changes,

[code]
HRESULT CMesh::LoadMesh(const char *szfilename)
{

char szPath[1024];
CAllocateHierarchy Alloc;
PBYTE pMappedFileBase = NULL;



// unload these functions to a dll
::GetModuleFileNameA(NULL, szPath, sizeof(szPath));

strcat (szPath, szfilename);


FILE *fp = fopen (szPath, "rb");
if (fp == NULL)
OutputDebugStringA("File open error\n");
__int64 si = FileSize64(szPath);


int actlen = si-4;


std::vector<BYTE> v(actlen);

pMappedFileBase = &v[0];

memset (pMappedFileBase, 0, actlen);

fseek(fp, 4, SEEK_SET);
fread(pMappedFileBase, sizeof(BYTE), actlen, fp);

int size_template = sizeof(template_bin);
int j = actlen+size_template;


std::vector<BYTE> v2(j);
PBYTE pBin = &v2[0];

int x;
for (x = 0; x < size_template; x++)
{
pBin[x] = template_bin[x];
}


int i = 0;
for (; x < j;x++,i++)
{

pBin[x] = pMappedFileBase[i];
}
assert(x == j);
HRESULT hr = S_OK;


// Build a new parser?
hr = D3DXLoadMeshHierarchyFromXInMemory((LPCVOID) pBin, j,
D3DXMESH_MANAGED, m_pDevice, &Alloc,
NULL, (LPD3DXFRAME*)&m_pFrameRoot, &m_pAnimController);


if (FAILED(hr))
{
MessageBoxA(NULL, "Can't load mesh", "Error", MB_OK);
}


fclose(fp);
return hr;


}

[/code]

Thanks
Jack
Jack
2009-12-18 13:34:01 UTC
Permalink
Post by Jack
memset (pMappedFileBase, 0, actlen);
This line had already been cancelled.
Sorry, I know I am very careless :)
Thanks
Jack
Igor Tandetnik
2009-12-18 13:45:27 UTC
Permalink
Post by Jack
[code]
HRESULT CMesh::LoadMesh(const char *szfilename)
{
char szPath[1024];
CAllocateHierarchy Alloc;
PBYTE pMappedFileBase = NULL;
// unload these functions to a dll
Post by Jack
GetModuleFileNameA(NULL, szPath, sizeof(szPath));
strcat (szPath, szfilename);
FILE *fp = fopen (szPath, "rb");
Does this succeed? szPath currently contains something like

c:\somepath\yourapp.exesomefilename

This is unlikely to refer to an actual file.
Post by Jack
if (fp == NULL)
OutputDebugStringA("File open error\n");
__int64 si = FileSize64(szPath);
What's the value of si here? If szPath is in fact invalid, it's probably zeo.
Post by Jack
int actlen = si-4;
And if si is zero, then actlen (when cast to unsigned int) is a very large value.
Post by Jack
int size_template = sizeof(template_bin);
What's template_bin?
Post by Jack
int j = actlen+size_template;
std::vector<BYTE> v2(j);
PBYTE pBin = &v2[0];
int x;
for (x = 0; x < size_template; x++)
{
pBin[x] = template_bin[x];
}
int i = 0;
for (; x < j;x++,i++)
{
pBin[x] = pMappedFileBase[i];
}
assert(x == j);
It appears that these two loops can be replaced with this:

memcpy(pBin, template_bin, size_template);
memcpy(pBin + size_template, pMappedFileBase, actlen);
Post by Jack
// Build a new parser?
hr = D3DXLoadMeshHierarchyFromXInMemory((LPCVOID) pBin, j,
D3DXMESH_MANAGED, m_pDevice, &Alloc,
NULL, (LPD3DXFRAME*)&m_pFrameRoot, &m_pAnimController);
I don't know anything about Direct3D. However, I find it surprising that you are passing a pointer to a stack-allocated object (Alloc) where an interface pointer is required. It seems reasonable to expect that D3DXLoadMeshHierarchyFromXInMemory would want to AddRef this pointer and keep it around until such time as the mesh needs to be disposed of. But your object will die at the end of the function, regardless of its reference count.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Jack
2009-12-18 14:03:46 UTC
Permalink
Hello Igor,
Thanks for coming back!
Post by Jack
[code]
HRESULT CMesh::LoadMesh(const char *szfilename)
{
char szPath[1024];
CAllocateHierarchy Alloc;
PBYTE pMappedFileBase = NULL;
// unload these functions to a dll
Post by Jack
GetModuleFileNameA(NULL, szPath, sizeof(szPath));
strcat (szPath, szfilename);
FILE *fp = fopen (szPath, "rb");
Does this succeed? szPath currently contains something like

c:\somepath\yourapp.exesomefilename

This is unlikely to refer to an actual file.

J: The open operation does succeed.
Post by Jack
if (fp == NULL)
OutputDebugStringA("File open error\n");
__int64 si = FileSize64(szPath);
What's the value of si here? If szPath is in fact invalid, it's probably
zeo.

J: si = 2541334 in decimal or 0x26c716 in hex
Range from 0x14D0040 to 0x173C756
excluding the leading and trailing 0xfd's
Post by Jack
int actlen = si-4;
And if si is zero, then actlen (when cast to unsigned int) is a very large
value.

J: The var appears to be normal.
Post by Jack
int size_template = sizeof(template_bin);
What's template_bin?

J:
static BYTE template_bin[] = {
0x78,0x6f,0x66,0x20,0x30,0x33,0x30,0x33,0x62,0x69,0x6e,0x20,0x30,0x30,0x33,0x32,
0x1f,0x00,0x01,0x00,0x0f,0x00,0x00,0x00,0x58,0x53,0x6b,0x69,0x6e,0x4d,0x65,0x73,
0x68,0x48,0x65,0x61,0x64,0x65,0x72,0x0a,0x00,0x05,0x00,0xce,0x69,0xf1,0x3c,0x7c,
0xff,0xab,0x44,0x93,0xc0,0xf7,0x8f,0x62,0xd1,0x72,0xe2,0x28,0x00,0x01,0x00,0x18,
0x00,0x00,0x00,0x6e,0x4d,0x61,0x78,0x53,0x6b,0x69,0x6e,0x57,0x65,0x69,0x67,0x68,
0x74,0x73,0x50,0x65,0x72,0x56,0x65,0x72,0x74,0x65,0x78,0x14,0x00,0x28,0x00,0x01,
0x00,0x16,0x00,0x00,0x00,0x6e,0x4d,0x61,0x78,0x53,0x6b,0x69,0x6e,0x57,0x65,0x69,
0x67,0x68,0x74,0x73,0x50,0x65,0x72,0x46,0x61,0x63,0x65,0x14,0x00,0x28,0x00,0x01,
0x00,0x06,0x00,0x00,0x00,0x6e,0x42,0x6f,0x6e,0x65,0x73,0x14,0x00,0x0b,0x00,0x1f,
0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x56,0x65,0x72,0x74,0x65,0x78,0x44,0x75,0x70,
0x6c,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x49,0x6e,0x64,0x69,0x63,0x65,0x73,0x0a,
0x00,0x05,0x00,0x49,0x55,0xd6,0xb8,0xc9,0xd7,0x95,0x49,0x89,0xcf,0x53,0xa9,0xa8,
0xb0,0x31,0xe3,0x29,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x6e,0x49,0x6e,0x64,0x69,
0x63,0x65,0x73,0x14,0x00,0x29,0x00,0x01,0x00,0x11,0x00,0x00,0x00,0x6e,0x4f,0x72,
0x69,0x67,0x69,0x6e,0x61,0x6c,0x56,0x65,0x72,0x74,0x69,0x63,0x65,0x73,0x14,0x00,
0x34,0x00,0x29,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x69,0x6e,0x64,0x69,0x63,0x65,
0x73,0x0e,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x6e,0x49,0x6e,0x64,0x69,0x63,0x65,
0x73,0x0f,0x00,0x14,0x00,0x0b,0x00,0x1f,0x00,0x01,0x00,0x0b,0x00,0x00,0x00,0x53,
0x6b,0x69,0x6e,0x57,0x65,0x69,0x67,0x68,0x74,0x73,0x0a,0x00,0x05,0x00,0x3b,0x12,
0x0d,0x6f,0xd2,0xba,0x67,0x41,0xa0,0xd0,0x80,0x22,0x4f,0x25,0xfa,0xbb,0x31,0x00,
0x01,0x00,0x11,0x00,0x00,0x00,0x74,0x72,0x61,0x6e,0x73,0x66,0x6f,0x72,0x6d,0x4e,
0x6f,0x64,0x65,0x4e,0x61,0x6d,0x65,0x14,0x00,0x29,0x00,0x01,0x00,0x08,0x00,0x00,
0x00,0x6e,0x57,0x65,0x69,0x67,0x68,0x74,0x73,0x14,0x00,0x34,0x00,0x29,0x00,0x01,
0x00,0x0d,0x00,0x00,0x00,0x76,0x65,0x72,0x74,0x65,0x78,0x49,0x6e,0x64,0x69,0x63,
0x65,0x73,0x0e,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x6e,0x57,0x65,0x69,0x67,0x68,
0x74,0x73,0x0f,0x00,0x14,0x00,0x34,0x00,0x2a,0x00,0x01,0x00,0x07,0x00,0x00,0x00,
0x77,0x65,0x69,0x67,0x68,0x74,0x73,0x0e,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x6e,
0x57,0x65,0x69,0x67,0x68,0x74,0x73,0x0f,0x00,0x14,0x00,0x01,0x00,0x09,0x00,0x00,
0x00,0x4d,0x61,0x74,0x72,0x69,0x78,0x34,0x78,0x34,0x01,0x00,0x0c,0x00,0x00,0x00,
0x6d,0x61,0x74,0x72,0x69,0x78,0x4f,0x66,0x66,0x73,0x65,0x74,0x14,0x00,0x0b,0x00
};
Post by Jack
int j = actlen+size_template;
std::vector<BYTE> v2(j);
PBYTE pBin = &v2[0];
int x;
for (x = 0; x < size_template; x++)
{
pBin[x] = template_bin[x];
}
int i = 0;
for (; x < j;x++,i++)
{
pBin[x] = pMappedFileBase[i];
}
assert(x == j);
It appears that these two loops can be replaced with this:

memcpy(pBin, template_bin, size_template);
memcpy(pBin + size_template, pMappedFileBase, actlen);

J: Hmm.. tried that but still leaking.
Post by Jack
// Build a new parser?
hr = D3DXLoadMeshHierarchyFromXInMemory((LPCVOID) pBin, j,
D3DXMESH_MANAGED, m_pDevice, &Alloc,
NULL, (LPD3DXFRAME*)&m_pFrameRoot, &m_pAnimController);
I don't know anything about Direct3D. However, I find it surprising that you
are passing a pointer to a stack-allocated object (Alloc) where an interface
pointer is required. It seems reasonable to expect that
D3DXLoadMeshHierarchyFromXInMemory would want to AddRef this pointer and
keep it around until such time as the mesh needs to be disposed of. But your
object will die at the end of the function, regardless of its reference
count.

J: Ah... let me look into this further. Give me some time
Because I recall one time when I blocked out this line,
the application then stopped leaking...

Thanks a lot Igor, your great!
Jack
Jack
2009-12-18 14:12:36 UTC
Permalink
Post by Igor Tandetnik
Post by Jack
hr = D3DXLoadMeshHierarchyFromXInMemory((LPCVOID) pBin, j,
D3DXMESH_MANAGED, m_pDevice, &Alloc,
NULL, (LPD3DXFRAME*)&m_pFrameRoot, &m_pAnimController);
I don't know anything about Direct3D. However, I find it surprising that
you are passing a pointer to a stack-allocated object (Alloc) where an
interface pointer is required. It seems reasonable to expect that
D3DXLoadMeshHierarchyFromXInMemory would want to AddRef this pointer and
keep it around until such time as the mesh needs to be disposed of. But
your object will die at the end of the function, regardless of its
reference count.
J: Ah... let me look into this further. Give me some time
Because I recall one time when I blocked out this line,
the application then stopped leaking...
Thanks a lot Igor, your great!
Jack
Hi Igor,
Ah... Seems to be this function having problems. How can I modify that to
stop the leak?
CAllocateHierachy is a class that is derived from ID3DXAllocateHierachy. And
I overrided
its pure virtual methods and it is used as the callback when I load in a
mesh.

Thanks
Jack
Igor Tandetnik
2009-12-18 14:20:39 UTC
Permalink
Post by Jack
Post by Jack
hr = D3DXLoadMeshHierarchyFromXInMemory((LPCVOID) pBin, j,
D3DXMESH_MANAGED, m_pDevice, &Alloc,
NULL, (LPD3DXFRAME*)&m_pFrameRoot, &m_pAnimController);
Ah... Seems to be this function having problems.
Most likely, the problem is not in the API function itself, but in your code that this function relies on.
Post by Jack
How can I modify that to stop the leak?
Obviously, you debug your code, figure out what you are doing wrong, and fix that.
Post by Jack
CAllocateHierachy is a class that is derived from ID3DXAllocateHierachy. And
I overrided
its pure virtual methods and it is used as the callback when I load in a
mesh.
So, there is likely a problem with your implementation of ID3DXAllocateHierachy.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Loading...