Heap corruption

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
flatmush
Posts: 28
Joined: Tue Aug 07, 2007 9:15 am
Location: Here
Contact:

Heap corruption

Post by flatmush »

I know heap corruption is one of the ultimate evils of psp homebrew as we don't have the same dev tools as the official sony devs do. I assume the extra 32mb of memory they get is partially for memory error checking.

Anyway to the point, I am pretty sure my program has a heap corruption problem somewhere, however it is a large project and I am finding it _very_ difficult to find the error by eye, when using psplink my program crashes without exception causing the psp to shutoff after a few seconds.

My question is does anybody have any good tips for finding memory overflows and general heap corruption, or is there a way I could write some sort of heap debugger into my program easily (bearing in mind that my program uses a wrapper function for malloc so I can insert code in all malloc calls if need be) ?
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

A lot of people write 'sentinel' values into their allocations, so when you wrap malloc, alloc an extra trio of dwords, one at the beginning, the allocation size, and one at the end, and write magic values in there (eg. 0xdeadbeef or 0x0badf00d). When you free the allocation, check to make sure these haven't been overwritten.
so something like (untested)

Code: Select all

void *mymalloc(size_t size)
{
  char *mem;
/*you want to round size up to the next multiple of 4 to avoid alignment problems*/
  size += (4-(size&3))&3;
  mem = malloc(size + 12);
  *(int *)mem = 0xdeadbeef;
  *(size_t *)(mem+4) = size;
  *(int *)(mem+size+8) = 0x0badf00d;
  return mem+8;
}

void myfree(void *mptr)
{
  char *mem = (char *)mptr-8;
  size_t size;
  assert(*(int *)mem == 0xdeadbeef);
  size = *(size_t *)(mem+4);
  assert(*(int *)(mem+size+8) == 0x0badf00d);
  free(mem);
}
The developers' extra 32megs is usually so they can worry about making the game work in the early stages of development without having to worry about cramming it in to a tiny memory space. That problem can usually be left to the end, if necessary.

Jim
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

In addition to what Jim said, you can also keep a global list of all blocks of memory that you've allocated, and create a function that rechecks all the sentinels. Then just sprinkle calls to that function all over your code and you'll notice corruption even before a free().
flatmush
Posts: 28
Joined: Tue Aug 07, 2007 9:15 am
Location: Here
Contact:

Post by flatmush »

OK, thanks for all the replies. I implemented an error checker and a linked list containing allocation information (only used when compiled with debugging). I have tested it on lots of situations and it seems pretty tight, so my problem now is that the main original problem I have may not have been due to heap corruption.

I have 2 problems at the minute which I am having great trouble tracking down.
1. Certain projects just crash when memory error checking is enabled, I doubt it is todo with the code being wrong so maybe the projects rely on memory being initialized in a certain way or something.
2. I am getting seemingly random heap corruption, which I don't think is todo with over/under flows.

I doubt the root of my problem is todo with stack overflows either, is there anything else that could cause the above problems.
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

Certain projects just crash when memory error checking is enabled
Until you fix that, there's no reason to believe your heap isn't being corrupted. Perhaps try adding some more blank space to the beginning and end of the allocations (instead of just one dword) - perhaps you're overstepping by a larger amount.

Try removing parts of the program until it goes away.
maybe the projects rely on memory being initialized in a certain way or something.
Why would that be?

Jim
danzel
Posts: 182
Joined: Fri Nov 04, 2005 11:03 pm

Post by danzel »

Depending on how portable your code is, you may be able to get it to compile on Linux and use valgrind to track down where your errors are happening.
flatmush
Posts: 28
Joined: Tue Aug 07, 2007 9:15 am
Location: Here
Contact:

Post by flatmush »

OK, I thought it would be rude not to reply after all the help you guys have given me, so thanks.

The system I have now allocates n bytes at the beginning and end of the data where n is the byte alignment, in the 16 bytes closest to the data it contains the blocks size, alignment and then the 8 bytes closest to the data at each end contain 4 different identifiable hex strings to make it easy to see when debugging.

I also add all allocations to a linked list that contains the size, alignment and a pointer to the memory block.

Then after each memory operation memSet/memClear/memCopy/memAlloc/memFree/etc. I call a test algorithm that scans every block in the list for inconsistencies and reports an overflow or an underflow.

It did work, and found a few small errors in an old function used for finding file extensions, but frustratingly I don't think my problems were memory related anyway, I think the problem was a logical error todo with pointers in my model rendering code.
Post Reply