Best practices for unknown data static/dynamic allocation origin

Discussion in 'C Programming' started by riccardo, Oct 28, 2010.

  1. riccardo

    riccardo Guest

    Hi,
    I'm wondering what the best practice is when, within a function you need
    to know if a variable was allocated statically or dynamically, in order
    to eventually free it.

    I'm dealing with a scheduler that consume tasks. Once a task is
    consumed, the scheduler has to release the memory owned by that task,
    and this is a responsibility of the scheduler only (not the one entity
    that allocated the task).

    Three approaches come to my mind:
    1) Documentation: document the function to add a new task to the
    scheduler, requesting the input argument to be a dynamically allocated task.

    2) Insert a flag in the task data structure to signal its origin (static
    vs dynamic).

    3) malloc a task and copy data into that task. All tasks shall need to
    be free @removal.

    I'm currently using 3 as it seems the cleaner ans safer solution; is
    this correct? Is there any other way?
    RM
    riccardo, Oct 28, 2010
    #1
    1. Advertising

  2. riccardo

    Nobody Guest

    On Thu, 28 Oct 2010 16:13:36 +0200, riccardo wrote:

    > I'm wondering what the best practice is when, within a function you need
    > to know if a variable was allocated statically or dynamically, in order
    > to eventually free it.


    The most general case is to require the caller to provide a callback
    function to free the data. For static (or automatic) storage, this can be
    a no-op. Dynamic storage may require a "matching" deallocator, i.e. you
    can't assume the existence of a single deallocator which works with any
    and all dynamically-allocated memory.

    E.g. on Windows, a program may be linked with multiple DLLs, and different
    DLLs may be linked with different versions of MSVCRT. Each version of
    MSVCRT maintains its own heap, so anything allocated by that version's
    malloc() (etc) must be deallocated using the same version's free(). If you
    use the wrong free() function, it's likely to crash.

    If you have multiple pointers to dynamic storage, you may need a separate
    deallocator for each one.
    Nobody, Oct 28, 2010
    #2
    1. Advertising

  3. riccardo

    BartC Guest

    "riccardo" <> wrote in message
    news:iac0ee$i85$...

    > I'm wondering what the best practice is when, within a function you need
    > to know if a variable was allocated statically or dynamically, in order to
    > eventually free it.
    >
    > I'm dealing with a scheduler that consume tasks. Once a task is consumed,
    > the scheduler has to release the memory owned by that task, and this is a
    > responsibility of the scheduler only (not the one entity that allocated
    > the task).
    >
    > Three approaches come to my mind:
    > 1) Documentation: document the function to add a new task to the
    > scheduler, requesting the input argument to be a dynamically allocated
    > task.
    >
    > 2) Insert a flag in the task data structure to signal its origin (static
    > vs dynamic).
    >
    > 3) malloc a task and copy data into that task. All tasks shall need to be
    > free @removal.
    >
    > I'm currently using 3 as it seems the cleaner ans safer solution; is this
    > correct? Is there any other way?


    Garbage collection?

    --
    bartc
    BartC, Oct 29, 2010
    #3
  4. riccardo

    Eric Sosman Guest

    On 10/28/2010 10:13 AM, riccardo wrote:
    > Hi,
    > I'm wondering what the best practice is when, within a function you need
    > to know if a variable was allocated statically or dynamically, in order
    > to eventually free it.


    You probably already know that there is no portable way to examine
    a block of memory, or a pointer to a block of memory, and arrive at
    the answer you seek. On some systems you might be able to convert a
    pointer to an integer and make some deductions based on the integer's
    value ("addresses M to N are code, N to P are stack, P to Q are data,
    everything else is mallocated"), but even then there's no way to tell
    whether a pointer into mallocated memory is a pointer to the start of
    a mallocated block or to somewhere in its middle.

    But the question isn't really "was it mallocated or not," rather
    "should I free it?" You certainly should not free memory that wasn't
    obtained from malloc, but it is not a foregone conclusion that memory
    from malloc ought to be freed by this service function of yours! It
    is entirely possible that the caller might have further use for the
    memory after you're through with it; you're not in a position to know.

    > I'm dealing with a scheduler that consume tasks. Once a task is
    > consumed, the scheduler has to release the memory owned by that task,
    > and this is a responsibility of the scheduler only (not the one entity
    > that allocated the task).
    >
    > Three approaches come to my mind:
    > 1) Documentation: document the function to add a new task to the
    > scheduler, requesting the input argument to be a dynamically allocated
    > task.
    >
    > 2) Insert a flag in the task data structure to signal its origin (static
    > vs dynamic).
    >
    > 3) malloc a task and copy data into that task. All tasks shall need to
    > be free @removal.
    >
    > I'm currently using 3 as it seems the cleaner ans safer solution; is
    > this correct? Is there any other way?


    The caller probably needs to insert some information into this
    "task" object before your function can make sense of it. Perhaps you
    should keep the "task" private and internal, and expose only a suite
    of functions that set (and perhaps query) its characteristics:

    typedef struct opaque_struct Task;
    Task *newEmptyTask(void);
    void setPriority(Task *task, int priority);
    void setFrazzleString(Task *task, const char *frazzle);
    Task *copyExistingTask(const Task *oldTask);
    ...
    void performTask(Task *task);
    void destroyTask(Task *hes_dead_jim);
    ...

    An approach of this kind allows you to manage all the resources
    of a Task internally, which you may find convenient. It also allows
    you to change the nature of a Task without disturbing your clients or
    even requiring their recompilation: You can quite easily add

    void setColor(Task *task, TaskColor hue);

    to the package, provide a suitable default color for pre-existing code
    that is color-blind, and proceed merrily along. "Encapsulation" may
    offer benefits that go well beyond solving your present difficulty.

    --
    Eric Sosman
    lid
    Eric Sosman, Oct 29, 2010
    #4
  5. On Oct 28, 4:13 pm, riccardo <> wrote:
    > Hi,
    > I'm wondering what the best practice is when, within a function you need
    > to know if a variable was allocated statically or dynamically, in order
    > to eventually free it.
    >

    Another way is to provide / require a destructor. This take the task
    as a pointer. If the task contains no dynamic data, it's simply a no-
    op. Otherwise it frees the allocated elements. The advantage is that
    you can have a tree or similar structure that is hard to create with a
    single call to malloc().
    Malcolm McLean, Nov 1, 2010
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ken
    Replies:
    24
    Views:
    3,839
    Ben Bacarisse
    Nov 30, 2006
  2. chris
    Replies:
    6
    Views:
    974
    chris
    Oct 28, 2005
  3. Guest
    Replies:
    5
    Views:
    415
    Scott David Daniels
    Mar 30, 2007
  4. Vincent Arnoux
    Replies:
    1
    Views:
    236
    Arnaud Bergeron
    Aug 11, 2006
  5. Sam
    Replies:
    10
    Views:
    56
    flebber
    Feb 15, 2014
Loading...

Share This Page