Should one really set pointers to `NULL` after freeing them?

前端 未结 10 1062
庸人自扰
庸人自扰 2020-11-28 03:27

There seem to be two arguments why one should set a pointer to NULL after freeing them.

Avoid crashing when double-freeing pointers.

Short

10条回答
  •  抹茶落季
    2020-11-28 03:44

    These problems are most often only symptoms for a much deeper problem. This can occur for all resources that require aquisition and a later release, e.g. memory, files, databases, network connections, etc. The core problem is that you've lost track of the resource allocations by a missing code structure, throwing random mallocs and frees all over the code base.

    Organize the code around DRY - Don't Repeat Yourself. Keep related things together. Do one thing only, and do it good. The "module" that allocates a resource is responsible for releasing it and has to provide a function for doing so that keeps care for the pointers, too. For any specific resource, you then have exactly one place where it is allocated and one place where it is released, both close together.

    Say you want to split a string into substrings. Directly using malloc(), your function has to care for everything: Analysing the string, allocate the right amount of memory, copy the substrings there, and and and. Make the function complicated enough, and it is not the question if you will lose track of the resources, but when.

    Your first module takes care for the actual memory allocation:

    
        void *MemoryAlloc (size_t size)
        void  MemoryFree (void *ptr)
    

    There's your only place in your whole codebase where malloc() and free() are called.

    Then we need to allocate strings:

    
        StringAlloc (char **str, size_t len)
        StringFree (char **str)
    

    They take care that len+1 is needed and that the pointer is set to NULL when freed. Provide another function to copy a substring:

    
        StringCopyPart (char **dst, const char *src, size_t index, size_t len)
    

    It will take care if index and len are inside the src string and modify it when needed. It will call StringAlloc for dst, and it will care that dst is correctly terminated.

    Now you can write your split function. You don't have to care for the low level details anymore, just analyse the string and get the substrings out of it. Most of the logic is now in the module where it belongs, instead of mixed together in one large monstrosity.

    Of course this solution has its own problems. It provides abstraction layers, and each layer, while solving other problems, comes with its own set of them.

提交回复
热议问题