[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 703
  • Last Modified:

malloc fails when passed a DWORD

For some reason malloc fails in one particular instance when I attempt to use it.  It is when I pass the return value of a function that simply returns a DWORD.  I multiply the DWORD by the size of a structure (which is 5), and the result in my tests is between 60 and 100, though it will be greater in actual use.  Essentially, I have this:

DWORD GetItemCount()
{
    return Whatever->ItemCount;
}

void OtherFunction()
{
    THESTRUCTURE *lpTest;
    lpTest = (THESTRUCTURE *)malloc(GetItemCount() * sizeof(THESTRUCTURE));
}

Every time I run the program it fails on the call to malloc.  If I subsitute a constant in in the place of GetItemCount() it succeeds.  As well, it does not fail if I am debugging.  Any ideas?

Thanks in advance,

Devin
0
DarkSnoopy
Asked:
DarkSnoopy
1 Solution
 
grg99Commented:
How about some debugging output:

DWORD Count, Size;

Count = GetItemCount();
Size   = Count * sizeof( THESTRUCTURE );

printf( "ITEMCOUNT = %d   Size = %d\n", Count, Size );

lpTest =  (THESTRUCTURE *) malloc( Size );

---------------------

You may be getting some strange overflow issues.

Either that or you're bashing the heap somehow.


0
 
DarkSnoopyAuthor Commented:
I took your suggestion and I get the following, as expected:
"Item Count = 5, Size = 80"

I don't know why it's failing... I've become so annoyed with it that I just cut the class containing this function out of the project it's a part of and just created a small console application with smaller values to test it out, so by the time it reaches this point in the program it's allocated no more than about 5 KB in addition to whatever console applications usually require on Windows.  I've even attempted just using a void pointer rather than casting it to a pointer to the structure I'm using.

In a function that is typically called just before the one that isn't working (and is being called before it in the test I've been trying to get it to work for) I have something similar to the following:


    DWORD dwSize = 0;
    dwSize += GetBlockCount() * sizeof(THEOTHERSTRUCTURE);
    dwSize += GetItemCount() * sizeof(THESTRUCTURE);
    m_lpStructure = malloc(dwSize + m_lpHeader->NameSize);

This works without error, so I fail to see why something so similar fails.  It seems even odder that I can go through all of the code in question, line by line, while debugging and no error occurs whatsoever.  Even if I just let the debugger run it and have no breakpoints it still runs just fine.  It's only when I'm executing it separately that it has this problem.  Nothing further happens after the call to malloc, it just dies.  According to Windows XP, the error is in ntdll.dll at offset 00011639.  I'm assuming that ntdll.dll contains the functions that look after memory allocation and such, so it makes sense that this is where the program would die.  The same code even works if I simply replace GetItemCount() with GetBlockCount(), but this won't do of course since the latter returns a much bigger value, and not the one that I am looking to use.  Each function is quite similar in nature though; a single line that returns the item count or block count from an array, using the index of the item that is currently being processed, and both return it as a DWORD.  The debugging output you suggested makes it fairly obvious that GetItemCount() is returning the right value, so I am still stumped.
0
 
baboo_Commented:
strange and strange...

I know that DWORD is essentially an int, but maybe try casting the DWORD to an int...  Hell, I don't even know if you're allowed to do it, but this is a total shot-in-the-dark WAG.

    THESTRUCTURE *lpTest;
    lpTest = (THESTRUCTURE *)malloc((int) GetItemCount() * sizeof(THESTRUCTURE));

Huh.  

baboo_
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
DarkSnoopyAuthor Commented:
I've tried it but it failed... thanks for the suggestion though!
0
 
ambienceCommented:
Try new and delete. By any chance of misfortune might it be a problen with different versions of the c-runtime? or perhaps improper initialization. Although never seen the later before, but thats probably the only that comes to mind at the moment. Is this inside a dll?
0
 
DarkSnoopyAuthor Commented:
No, it's not inside a dll.  What do you mean by "Try new and delete."?
0
 
grg99Commented:
My guess:  somewhere you're bashing memory just past an allocated block.  Very easy to do unless your malloc math is just right.  The bashing doesnt cause any immediate crash, but messes up the malloc linked list so sometime later when you call malloc, it fails.

One way to diagnose this-- kinda kludgy:  #define malloc(x)    malloc(x+5000)

if the code then works, yuo know what the problem is.  Then you have to find the problem.

0
 
DarkSnoopyAuthor Commented:
grg99, your suggestion made it work, but how do I know what the problem is?  I only call malloc at two other places in the program before that point.  The first time it's the sum of a series of sizeof things, and the second is the code I put above, which I'll paste here again.

    DWORD dwSize = 0;
    dwSize += GetBlockCount() * sizeof(THEOTHERSTRUCTURE);
    dwSize += GetItemCount() * sizeof(THESTRUCTURE);
    m_lpStructure = malloc(dwSize + m_lpHeader->NameSize);

I'm assuming the problem is with the second call, but how would I know?
0
 
grg99Commented:
Well, the only way is to peer at your code and make sure that your m_lpstructure pointer is always used to access fields in THESTRUCTURE, which I assume is somewhere declared to be right after THEOTHERSTRUCTURE (or vice-versa) and they're both followed by a string of "NameSize".

 BTW you probably need to add ONE MORE to that total to account for the trailing '\0' byte!  (Unless it's a fixed-size non-zero terinated string).

How about showing us your code, if it isnt too long?
0
 
DarkSnoopyAuthor Commented:
Before I say anything else, you're definitely gonna get more than 75 points for this grg99.  The code is a few pages, but I'll cut out what seems to be important and explain some parts of the rest that might be problematic.

// m_lpHeaders is a void pointer
    m_lpHeaders = malloc(sizeof(GCFHEADER) + sizeof(GCFBLOCKENTRYHEADER) + sizeof(GCFFRAGMAPHEADER) + sizeof(GCFDIRECTORYHEADER) +
        sizeof(GCFDIRECTORYMAPHEADER) + sizeof(GCFCHECKSUMHEADER) + sizeof(GCFCHECKSUMMAPHEADER));
    memset(m_lpHeaders, 0, sizeof(GCFHEADER) + sizeof(GCFBLOCKENTRYHEADER) + sizeof(GCFFRAGMAPHEADER) + sizeof(GCFDIRECTORYHEADER) +
        sizeof(GCFDIRECTORYMAPHEADER) + sizeof(GCFCHECKSUMHEADER) + sizeof(GCFDATABLOCKHEADER));

// the m_Headers structure contains pointers to structures of other types
    m_Headers.lpGCFHeader = (LPGCFHEADER)((_w64)m_lpHeaders);
    m_Headers.lpBlockEntryHeader = (LPGCFBLOCKENTRYHEADER)((_w64)m_Headers.lpGCFHeader + sizeof(GCFHEADER));
    m_Headers.lpFragMapHeader = (LPGCFFRAGMAPHEADER)((_w64)m_Headers.lpBlockEntryHeader + sizeof(GCFBLOCKENTRYHEADER));
    m_Headers.lpDirectoryHeader = (LPGCFDIRECTORYHEADER)((_w64)m_Headers.lpFragMapHeader + sizeof(GCFFRAGMAPHEADER));
    m_Headers.lpDirectoryMapHeader = (LPGCFDIRECTORYMAPHEADER)((_w64)m_Headers.lpDirectoryHeader + sizeof(GCFDIRECTORYHEADER));
    m_Headers.lpChecksumHeader = (LPGCFCHECKSUMHEADER)((_w64)m_Headers.lpDirectoryMapHeader + sizeof(GCFDIRECTORYMAPHEADER));
    m_Headers.lpDataBlockHeader = (LPGCFDATABLOCKHEADER)((_w64)m_Headers.lpChecksumHeader + sizeof(GCFCHECKSUMHEADER));

    DWORD dwSize = 0;
    dwSize += GetBlockCount() * sizeof(GCFBLOCKENTRY);
    dwSize += GetBlockCount() * sizeof(GCFFRAGMAP);
    dwSize += GetItemCount() * sizeof(GCFDIRECTORYENTRY);
    dwSize += GetItemCount() * sizeof(GCFDIRECTORYMAPENTRY);

// m_lpStructure is a void pointer
    m_lpStructure = malloc(dwSize + m_Headers.lpDirectoryHeader->NameSize);
    memset(m_lpStructure, 0, dwSize + m_Headers.lpDirectoryHeader->NameSize);

// m_Structure contains pointers to structures of other types
    m_Structure.lpBlockEntry = (LPGCFBLOCKENTRY)((_w64)m_lpStructure);
    m_Structure.lpFragMap = (LPGCFFRAGMAP)((_w64)m_Structure.lpBlockEntry + GetBlockCount() * sizeof(GCFBLOCKENTRY));
    m_Structure.lpDirectoryEntry = (LPGCFDIRECTORYENTRY)((_w64)m_Structure.lpFragMap + GetBlockCount() * sizeof(GCFFRAGMAP));
    m_Structure.lpDirectoryMapEntry = (LPGCFDIRECTORYMAPENTRY)((_w64)m_Structure.lpDirectoryEntry + GetItemCount() * sizeof(GCFDIRECTORYENTRY));
    m_Structure.lpszDirectoryNames = (LPSTR)((_w64)m_Structure.lpDirectoryMapEntry + GetItemCount() * sizeof(GCFDIRECTORYMAPENTRY));

// This is the code that I have given you a modified version of previously
    DWORD dwCount = GetItemCount();
    DWORD dwSize = 0;
    dwSize += dwCount * sizeof(GCFITEMMAP);
    printf("Item Count = %d   Size = %d\n", dwCount, dwSize);
    m_lpItemMap = (LPGCFITEMMAP)malloc((int)dwSize);

Basically I wanted the memory for the different headers and the memory for the different structural elements to be contiguous so I allocated all the memory I would need for them with a void pointer then used other pointers that are a certain offset from that pointer to access the data.  To clear up the NameSize thing, NameSize already accounts for the trailing \0 and is actually a fairly long list of null-terminated strings that could be several kilobytes in length.
0
 
grg99Commented:
Holy moly, that's really tricky code!

One way you can narrow down where the bashing is happening is to sprinkle calls to a heap exercizer function thuout your code, something like:

void CheckHeap( char * Msg )
{
  int i;
  for( i = 3; i < 30000; i *= 2 )  free( malloc( i ) );
  printf("Heap may be okay at %s\n", Msg );
}
 
That may narrow sown the problem area.
0
 
DarkSnoopyAuthor Commented:
Thank you very much grg99!  Placing the heap exercizer function before the first line of code that I gave you caused the program to execute properly.  I looked through the code immediately after it and noticed that I added sizeof(GCFCHECKSUMMAPHEADER) instead of sizeof(GCFDATABLOCKHEADER).  I guess it happened when I removed GCFCHECKSUMMAPHEADER from the GCFHEADERS structure, I must have deleted the wrong sizeof call.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now