3

Let's say I declare the following array:

char *arr[3];

During running the program, depending on the user's inputs, I may or may not allocate strings of memory into this array (meaning arr[i]).

Is it safe to free(arr[i]) at the end of the program without checking which of them I allocated? Or could this cause errors?

Thanks!

Rohan Bari
  • 7,482
  • 3
  • 14
  • 34
Guy
  • 155
  • 11
  • 6
    It's safe if `arr[i]` points to `NULL`, calling `free` with an uninitialized pointer is undefined behaviour. – David Ranieri Jan 23 '21 at 19:31
  • 2
    Calling free on `char *arr[3];` is [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior). On some platforms, it could cause a segmentation violation. On *all* platforms - it's just "wrong". Don't do it! See also: [free() function without malloc or calloc](https://stackoverflow.com/questions/4110767/free-function-without-malloc-or-calloc) – paulsm4 Jan 23 '21 at 19:50
  • @paulsm4: if `char *arr[3];` is defined as a global variable, it will be initialized to null pointers and calling `free(arr[0])` will be fine. Can you be more specific? – chqrlie Jan 23 '21 at 20:01

2 Answers2

0

It is safe to pass a null pointer to free, so if your array is initialized with null pointers, you can safely free all arr[i], assuming you only store pointers return by malloc() and friends and do not free them elsewhere.

Define the array as

char *arr[3] = { NULL, NULL, NULL };

or simply

char *arr[3] = { 0 };

NULL, 0 and '\0' may be used to specify a null pointer, but it is advisable to follow a simple rule of clarity:

  • use NULL for a null pointer,
  • use 0 for a null integer,
  • use '\0' for a null byte in an array of char, which is also called the null terminator.

And you can use = { 0 }; as an initializer for any C object: all elements and members will be intialized to the zero value of their type, except for unions where only the first member is initialized this way.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • One question, can we put `\0` instead of `NULL`? – Rohan Bari Jan 23 '21 at 19:36
  • 4
    @RohanBari: If you mean `'\0'`, technically yes, because `'\0'` is an `int` constant with the value `0`, therefore it is a null pointer in a pointer context. But it would be **very confusing** to use a character constant to initialize a pointer. `char *arr[3]` is an array of 3 pointers, not a pointer to an array of 3 `char`, which is written `char (*arr)[3]`. More details here: https://stackoverflow.com/questions/1296843/what-is-the-difference-between-null-0-and-0 – chqrlie Jan 23 '21 at 19:39
  • Mhmm... It's clearer to me now. Thanks! I'll take a deeper look at their differences. +1 – Rohan Bari Jan 23 '21 at 19:42
  • 1
    Here is a simple rule of clarity: use `NULL` for a null pointer, `0` for a null integer, `'\0'` for a null byte in an array of `char`, which is also called the null terminator. – chqrlie Jan 23 '21 at 19:44
  • 3
    @chqrlie: I'd add another rule: Use `{0}` to zero-initialize all members of a (possibly nested) array or structure, regardless of types, in cases where no other values would make sense [e.g. if one has a structure that contains the number of valid items in an array, followed by the array, I'd regard the use of ...`0, {0}`... to initialize the count to zero and all items to zero cleaner than the explicit listing of values for all the elements. – supercat Jan 23 '21 at 19:53
  • 1
    Just because you "can", doesn't mean you "should". At best, deliberately calling "free()" on an object you know you didn't malloc() is "perverse". It's also unnecessary code/unnecessary runtime overhead/unneeded code bloat. At worst - it's a maintenance nightmare - and a potential bug waiting to happen as the code is modified. DON'T DO IT! – FoggyDay Jan 23 '21 at 20:33
  • @FoggyDay: calling `free` on a pointer you know is either `NULL` or an allocated block is fine and well defined. Testing for null in this case is just redundant. – chqrlie Jan 24 '21 at 10:09
0

The only safe values to pass to free are null pointers and values returned by malloc, and to be clear on that, those values returned by malloc shall only be freed once until next time they're returned by malloc (or calloc, or realloc).

autistic
  • 1
  • 3
  • 35
  • 80