To debug malloc, consider placing a space between your control structure and the start of user data, as well as between the end user data and the checksum. One fill byte must be 0x00 byte zero, so string operations are stopped; consider putting another as 0xFF. If you have a fixed pattern and a stain that has changed, you know something is out of control - but there is more chance that your sensitive management data will not be trampled. If you use 16 bytes of padding on either side of the space allotted to the user, you can go up to 4 bytes of zeros appropriately aligned (hence a null 4-byte integer) and possibly 0xFFFFFFFF for -1. In addition, since you are likely to round the requested size to a multiple of your base block size, set bytes that are not for the user to use with a known value, and confirm that they remain unchanged. This will detect one-over-all-length modifications, or just a few bytes over the allotted length, which might otherwise go unnoticed.
The only drawback of a null byte in padding is that you will not easily detect read operations that do not stop at the end of the allocated memory when searching for a null byte. You can get an idea of this by having an alternative that uses padding without zero bytes in it.
Another option is to try to completely separate your control data from the memory returned to the user. Of course, complete separation is impossible, but at least to maintain a list of distributions (with sizes and pointers) separately from the selected blocks. Again, this gives you protection by putting your precious management data away from uncontrolled memory loss operations. You are not completely protected from strange pointers, but you are better protected. (And you can still create buffer zones around the allocated space for recording detection without control). However, this design is noticeably different from the question.
Assuming you get a memory block from "malloc ()", then you would do it roughly:
void *my_malloc(size_t nbytes) { size_t reqblocks = (nbytes + sizeof(header) - 1) / sizeof(header); size_t reqspace = (reqblocks + 2) * sizeof(header) + 2 * sizeof(padding); void *space = malloc(reqspace); if (space == 0) return space; void *retval = (char *)space + sizeof(header) + sizeof(padding); header *head = space; head->next = ...next...; head->size = nbytes; ...set head padding to chosen value... ...set tail padding to chosen value... ...set gap between nbytes and block boundary to chosen value... return retval; }
There is some interpretation left ...
Jonathan leffler
source share