1

How can I deinitialize x inside the free_x function? I have to do it in order to fit to an API method. I can very easily deinitialize x just by assigning null to it but I have to do it inside the free_x function.

typedef struct
{
    int field1;
    void *field2;
}my_struct;

static my_struct var;

int main(void)
{
    void *x;

    alloc_x(&x);
    free_x(x); // x = NULL works but not allowed

    return 0;
}

void alloc_x(void **param)
{
    *param = (my_struct *)&var;
}

void free_x(void *param)
{
    // how can I free param here?
}
sanchop22
  • 2,729
  • 12
  • 43
  • 66
  • 5
    `*param = NULL;`.......?; – LPs Dec 15 '16 at 09:50
  • 2
    *param = NULL should work – A.N Dec 15 '16 at 09:51
  • The _address_ of the pointer? Or the address that the pointer _points_ to? – byxor Dec 15 '16 at 09:51
  • OT: The cast here `*param = (my_struct *)&var;` is useless. Just do `*param = &var;` – alk Dec 15 '16 at 09:52
  • "*How can I deinitialize x inside the free_x function?*" the same way you initialise it, just using a different value, namely `NULL`. – alk Dec 15 '16 at 09:54
  • I'm so sorry, free_x takes void *param as a parameter and not void **param. I've fixed it in my question. – sanchop22 Dec 15 '16 at 09:56
  • 1
    @sanchop22 Then you can't. If you want to alter what "the thing you pass into `free_x` points at" (i.e. set it to `NULL`) then you must pass in a pointer-to-a-pointer, like you do for `alloc_x`. – TripeHound Dec 15 '16 at 10:10
  • Why isn't `x = NULL;` allowed? – ergysdo Dec 15 '16 at 10:25
  • Your code, as posted in the question, is already complete and correct: you need do no more. Since you do not allocate memory (either on a heap or stack or elsewhere) then there is nothing to free. You are implementing an API, so it is the responsibility of the caller to clean up their pointer variables, so that they do not de-reference a value that has been `free_x`ed. Nothing more to do. – Evil Dog Pie Dec 15 '16 at 11:44

4 Answers4

2

Simple answer: your code is already complete, so do no more.

Explanation: You do not allocate memory (on a heap or stack or elsewhere) so there is nothing to free. You do not take ownership of any resources that have to be returned, of set any flags that need to be cleared, or increment any semaphores that need to be decremented, etc.

You are implementing an API, but just because there is a function prototype that does not mean your implementation has to do anything, if it doesn't need to. Just change the comment to explain that there is nothing to do and leave the function empty.

void alloc_x(void **param)
{
    *param = &var; // No need to cast here, just assign.
}

void free_x(void *param)
{
    // Nothing allocated, taken, incremented, etc. in alloc_x, so ...
    // nothing to free, release, decrement, etc. here in free_x.
}

The code that is using the API is expecting the memory behind the param or x pointer to have been freed after the call, so it shouldn't be doing anything with its variable afterwards anyway. It's not your problem if they do, but it will be your problem if you go diddling round with the caller's x variable!

Evil Dog Pie
  • 2,300
  • 2
  • 23
  • 46
  • You are answering a question that is not the asked one. Moreover the question `struct my_struct` has an internal pointer so, can be easily guessed that other `malloc`ated memories must be `free`d in `free_x` function. – LPs Dec 15 '16 at 13:00
  • +1 Bang on target. I agree, we don't need to do anything in this case. If the caller uses x after free_x(..) its not your problem – A.N Dec 15 '16 at 13:25
0

just write *param = NULL;

malloc returns void * and free takes void *, so some of your casts are meaningless, and you're always freeing a void * even if you're starting with some other sort of pointer.

instance
  • 1,366
  • 15
  • 23
0

I don't think its possible without changing the alloc_x function. One possible implementation is given below:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
    int field1;
    void *field2;
}my_struct;

static my_struct var;

void alloc_x(void **param)
{
    *param = malloc(sizeof(my_struct *));
    memcpy(*param,(my_struct *)&var,sizeof(my_struct *));
}

void free_x(void *param)
{
    free(param);
    // how can I free param here?
}
int main(void)
{
    void *x;

    alloc_x(&x);
    free_x(x); // x = NULL works but not allowed

    return 0;
}
A.N
  • 541
  • 2
  • 13
  • Exactly but I must not use malloc and free because we are working on a microcontroller and it is not allowed to use dynamic memory allocations even though it is possible. – sanchop22 Dec 15 '16 at 10:23
  • In that case may I ask why you need alloc_x and free_x at all??. Instead of function why not use a MACRO. like #define free_x(param) param = NULL – A.N Dec 15 '16 at 10:26
  • Because I have to implement free_x function in order to fit to an API function. I must have free_x(void *param) function and it is supposed to deinitialize x inside the function. – sanchop22 Dec 15 '16 at 10:29
  • I don't think you can deinitialize x inside free_x by passing it as *, better use MACRO's if thats the only requirement you have – A.N Dec 15 '16 at 10:34
0

A little bit triky, but you can do

#include <stdio.h>
#include <string.h>

typedef struct
{
    int field1;
    void *field2;
}my_struct;

static my_struct var;

void alloc_x(void **param)
{
    *param = (my_struct *)&var;
}

void free_x(void *param)
{
    memset(param, 0x00, sizeof(void *));
}

int main(void)
{
    void *x;

    alloc_x(&x);
    printf("Before: x=%p\n", x);
    free_x(&x);
    printf("After: x=%p\n", x);

    return 0;
}

or

void free_x(void *param)
{
    my_struct **p = param;

    *p = NULL;
}

Obviously it is valid only in using void *

LPs
  • 16,045
  • 8
  • 30
  • 61
  • This would destroy contents of var variable as well. Not sure if this is intended. – A.N Dec 15 '16 at 11:30
  • This is not good. Code that tries to change *private* values in another piece of code is either a bug by design or one waiting to happen. – Evil Dog Pie Dec 15 '16 at 12:05
  • @A.N I'm not getting you – LPs Dec 15 '16 at 12:57
  • @LPs Yes, when you are passed a pointer to a pointer, as is the case in the `alloc_x` function. The fact that only the pointer is passed to the `free_x` function indicates that the caller's copy (i.e. the original `x` variable) is not intended to be modified. If `x` were meant to be modified it would indeed have been passed as a pointer to a pointer. – Evil Dog Pie Dec 15 '16 at 13:00