-3

Newbie C question. I have dynamic int array "n" inside my "Array" struct, I created an instance "arr" of "Array", after some manipulations with custom write functions (not sure if they are right though) I want to delete "n".

int main() {
    Array arr = init_arr(5);
    for (int i = 0; i < arr.length; i++) {
        arr.n[i] = i;
    }
    print_arr(arr); // prints 0 1 2 3 4
    add_to_arr(&arr, 228);
    print_arr(arr); // prints 0 1 2 3 4 228
    remove_from_arr(&arr, 0);
    print_arr(arr); // prints 1 2 3 4 228
    free_arr(arr);
    // ? free_arr_IDK(&arr.n);
    // ? free(arr.n); // even with this function it wont delete
    print_arr(arr); // ??? prints 1 2 3 4 228
}

but after deleting an array and printing "arr.n", instead of mess of digits, it prints my array exactly as it was before calling free(). Output:

Array size: 5 {0 1 2 3 4 }
-- added <228> to end of array
Array size: 6 {0 1 2 3 4 228 }
-- removed element #0
Array size: 5 {1 2 3 4 228 }
Array size: 5 {1 2 3 4 228 }

Press any key to continue.

1. Is this behaviour expected? 2. If it's okay, which of functions really deletes "arr.n"? free_arr(arr) or free_arr(&arr)?

Full code

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    There is no guarantee using an invalid pointer will cause a crash, or anything interesting. It might look like it was still valid, and that's ok. – Deduplicator Jul 16 '17 at 16:52
  • @SeekAddo Since allocation and deallocation isn't part of the struct's ctors, the pointer `n` of the copied struct would still point to the same address. – Rotem Jul 16 '17 at 16:53

1 Answers1

3

All free() is required to do is return the allocated block to the heap - making it available again for allocation.

It does not modify the pointer, and it is not required to modify the data pointed to; it will normally retain its value until it is reallocated and reused for some other purpose. Accessing the memory after it has been returned to the heap is undefined behaviour and writing to it certainly an error.

It is good practice to set the pointer free'd to NULL after freeing it; that way any erroneous access through the pointer will be trapped, e.g.

void free_arr( Array* arr )
{
    free( *arr ) ;
    *arr = NULL ;
}

Note that since you have hidden the free in free_arr() you have to change the type of the argument to Array* in order to modify the caller's pointer (which is exactly why free() cannot do it). It is then called thus:

free_arr( &arr ) ;
Clifford
  • 88,407
  • 13
  • 85
  • 165