简体   繁体   中英

change pointer type from malloc type and free it. Does it lead to memory leak?

I use malloc to allocate memory which is used by a pointer type. And then I forcefully modify pointer type. use free func to release the memory block. I am curious to know whether memory leak happens?

I thought memroy was free by pointer type. "int *b" has wider range memory block than "char *a". I compile the following code and run it. No expection happens. Could somebody tell me what happens and why?

#include <stdlib.h>

int
main(int argc, char **argv) {
        char *a = (char*)malloc(sizeof(char));
        int *b = (int*)a;
        free(b);
}

The routines in the malloc family keep track of all the memory they reserve, including the sizes. When you pass an address to free , the routines look up the address in their records and release the amount of space that was allocated for it.

free is only passed an address. It has no information about the type of the pointer that the caller used as an argument. Because free is declared as void free(void *) , any pointer passed to it is automatically converted to void * , and free receives only that void * , not any information that it came from an int * or other type.

Just to illustrate a little more what some others have already said, try executing the following program:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char** argv) {
    char* b = (char*)malloc(0x01020304);
    strcpy(b, "ABCDEFG");
    for (int index = -16; index < 16; index++) {
        printf("%02x ", (unsigned char) *(b + index));
    }
    free(b);
    return 0;
}

The output of the program (which is basically a hex dump of the memory around the location of the buffer):

01 00 00 00 04 03 02 01 4e 00 00 00 fd fd fd fd 41 42 43 44 45 46 47 00 cd cd cd cd cd cd cd cd

You can see the content of the buffer (41 42 43 44 45 46 47 is ABCDEFG in hex). So, in this example, "b" just points to that location in memory, but before that there are more things. Just before the content there are four "fd" bytes (not really related to the question but it's interesting to know). This is a "fence" that is used to check if your program wrote outside the boundaries of the buffer. For instance, if you did something like *(b - 1) = 'A', the memory manager would detect this when freeing the block because it would see that the fence has been modified. There is a similar fence just at the end of the buffer (which is more likely to be overwritten that this one).

But apart from that, you can also see a little bit before that the length of the buffer itself (04 03 02 01). You have to take into account that intel uses little-endian notation for data, so the size in memory is stored backwards from what we humans expect.

So when you call free on the buffer, the memory manager just goes backwards from the position you pass as parameter and calculates the size of the buffer it has to free. The type of the pointer doesn't really matter.

I executed this in Visual Studio 2019 and debug, so if you try it yourself on another platform your mileage may vary (you may not even be able to find the block size because that info may be stored somewhere else in memory and what you have before the buffer is a pointer to that info), but the underlying idea is the same: the memory manager stores a lot of information about the block that you are allocating, as for instance the block size, so the type of the pointer you use in free does not really matter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM