5

I don't know how to reset the value field inside the Hello struct. It's a pointer pointed to an outside passed input argument.

typedef struct Hello {
 void *value;
} Hello;
Hello* create_hello() {
 Hello* hello = malloc(sizeof(Hello));
 hello->value = NULL;
 return hello;
}
set_value(Hello *hello, void *value) {
 hello->value = value;
}
void free_hello(Hello *hello) {
 /** Should I set the value to NULL before freeing the hello? */
 hello->value = NULL;
 
 /** Free the hello */
 free(hello);
 
 /** Set hello to NULL inside the free_hello()? */
 hello = NULL;
}

Here is the test_function:

test_function(void* value) {
 Hello *hello = create_hello();
 set_value(hello, value);
 
 free_hello(hello);
 
 /** Set hello to NULL inside the test_function()? */
 hello = NULL;
}
  1. Should I execute hello->value = NULL; inside the free_hello in order to reset the hello->value to the default NULL status?

  2. Should I execute hello = NULL; inside the free_hello() or test_function() after freeing the struct with free()?

user207421
312k44 gold badges322 silver badges493 bronze badges
asked Oct 14 at 3:21
1
  • 2
    As mentioned in the answer below, hello = NULL; in test_function has no effect because hello is a local. You could change test_function to get a void** (pointer to pointer), so that you'll be able to set the pointer on the caller side to NULL. Commented Oct 14 at 5:55

2 Answers 2

7

Should I call hello->value = NULL; inside the free_hello in order to reset the hello->value to the default NULL status?

There's no need because you call free(hello) on the next line, so the pointer value becomes indeterminate, effectively meaning you shouldn't read it.

Should I call hello = NULL; inside the free_hello() or test_function() after freeing the struct with free()?

Setting hello to NULL inside of free_hello has no effect because it's a local variable to the function. Whether you do so with the variable from the calling function depends on what you intend to do with it later, but is typically a good idea so you don't have a freed pointer dangling around.

answered Oct 14 at 3:29
Sign up to request clarification or add additional context in comments.

Comments

4

Some additional thoughts to @dbush good answer.


Should I execute hello->value = NULL; inside the free_hello in order to reset the hello->value to the default NULL status?

Right after free(hello);, as hello is indeterminant, attempting hello->value is undefined behavior (UB).

Debugging: Yet performing hello->value = NULL; before the free(hello) can improve debugging as it may improve the chance of detecting later invalid use of the pointer that was in hello->value. This generally improves detection yet not a certainly. The assignment hello->value = NULL; before the free(hello) may get optimized out by an intelligent compiler. One might need additional code (e.g. a cast to a volatile data) to prevent such optimization. Code could perform hello->value = NULL; only in debug mode, yet that carries a disadvantage of injecting a small change between the debug compilation and release one yet has consequences.

Security: performing hello->value = NULL; before the free(hello) might improve security by not leaving tell-tale information in the free'd memory. Again, this assignment may get optimized out as discussed above. Note that security of data is a deep subject and zeroing is only a beginner step.

I see usefulness in always performing hello->value = NULL; and little downside. Since it is not obviously needed, a comment should accompany such code to outline why it is there.

C23 offers a clean way to assign data that might otherwise get optimized out. memset_explicit() is self documenting, lessening the the needed for a comment as suggested above. As a standard library function, a good compiler can be expected to emit efficient code - perhaps just a simple assignment.

The purpose of this function is to make sensitive information stored in the object inaccessible C23dr § 7.26.6.2 2
The intention is that the memory store is always performed (i.e. never elided), regardless of optimizations. This is in contrast to calls to the memset function. Footnote 367

memset_explicit(&data, 0, sizeof data);
// or in OP's case: zero entire object that `hello` points to
memset_explicit(hello, 0, sizeof hello[0]);

Should I execute hello = NULL; inside the free_hello() or test_function() after freeing the struct with free()?

Again, this can improve debugging, yet may get optimized out. Likewise, if used, comment such code to explain its apparent unnecessity.

As @wohlstad suggested, a re-write of the function signature is useful to alleviate the calling code's needed to zero the pointer.

answered Oct 14 at 9:34

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.