Search code examples
cmallocdynamic-memory-allocationfree

Freeing a dynamically allocated string with an internal null byte


The following code allocates 256 bytes for a character array and then replaces the space with \0 (similar to what strtok and strsep do).

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

int main() {
  char *long_one = (char *)malloc(sizeof(char) * 256);
  strcpy(long_one, "Nutrition Facts");
  *(long_one+9) = '\0';
  free(long_one);
  return 1;
}

Does the free in line 8 free all 256 bytes, or only those up to and including the \0?


Solution

  • free doesn't treat memory as a null-terminated string like the string handling functions necessarily do, so yes, it would free all memory allocated by malloc.

    This makes sense given that malloc is used for many purposes other than dynamically allocated char arrays for the purposes of building strings.

    Additional notes

    • Don't cast malloc in C. Relevant reading: Should I cast the result of malloc (in C)?
    • sizeof(char) is 1, so you can just pass 256 to malloc.
    • You should be checking to see that malloc succeeded before using this memory.
    • *(long_one+9) = '\0'; is equivalently and more readably written as: long_one[9] = '\0';
    • There's no point in dynamically allocating in this scenario vs. automatic allocation. The memory size is not prohibitive for automatic storage duration, nor is there a concern about lifetimes for memory automatically allocated in main. You might better just: char long_one[256];
    • return 1; suggests the program exited with an error. There are three options available to you: return 0;; return EXIT_SUCCESS; or simply don't explicitly return anything. The main function implicitly returns 0 if there's no explicit return value.

    Given some of these suggestions your code might look like:

    #include <stdlib.h>
    #include <string.h>
    
    int main(void) {
        char *long_one = malloc(256);
        if (!long_one) {
            fprintf(stderr, "Dynamic memory allocation failed.\n");
            return EXIT_FAILURE;
        }
    
        strcpy(long_one, "Nutrition Facts");
        long_one[9] = '\0';
        free(long_one);
    
        return EXIT_SUCCESS;
    }