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
  • 6,770
  • 3
  • 12
  • 31
Guy
  • 125
  • 7
  • 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

1 Answers1

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
  • 114,102
  • 10
  • 108
  • 170
  • 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