freeing allocated memory

Discussion in 'C Programming' started by binaya, Oct 19, 2003.

  1. binaya

    binaya Guest

    Dear all,

    Say I allocate a block of memory using the command malloc.I
    have a question. Can I deallocate certain portion of it only during
    runtime ?

    For eg:

    Say I allocate 5 pointers to int as below.

    link=(int*)malloc(5*sizeof(int))



    But during runtime, I find that I only need the front 3 of them.ie
    I only need link,link+1 and link+2.

    If I don't need link+3 and link+4, can I free these last two
    pointers to int using the command free(link+3) ?



    If not, then what is the best way to do so ?
    Thanking you in advance.
    binaya, Oct 19, 2003
    #1
    1. Advertising

  2. binaya

    James Hu Guest

    On 2003-10-19, binaya <> wrote:
    > Say I allocate a block of memory using the command malloc.I
    > have a question. Can I deallocate certain portion of it only during
    > runtime ?


    If you want to shrink the amount of memory you initially allocated,
    you can use realloc().

    -- James
    James Hu, Oct 19, 2003
    #2
    1. Advertising

  3. "binaya" <> schrieb im Newsbeitrag
    news:...
    > Dear all,
    >
    > Say I allocate a block of memory using the command malloc.I
    > have a question. Can I deallocate certain portion of it only during
    > runtime ?
    >
    > For eg:
    >
    > Say I allocate 5 pointers to int as below.
    >
    > link=(int*)malloc(5*sizeof(int))
    >
    >
    >
    > But during runtime, I find that I only need the front 3 of them.ie
    > I only need link,link+1 and link+2.
    >
    > If I don't need link+3 and link+4, can I free these last two
    > pointers to int using the command free(link+3) ?
    >
    >
    >
    > If not, then what is the best way to do so ?
    > Thanking you in advance.


    #include <stdlib.h>

    int main(void)
    {
    int *tmp;
    int *my_array = malloc(5 * sizeof *my_array);

    if(my_array)
    {
    my_array[0] = 100;
    my_array[1] = 200;
    my_array[2] = 300;
    /*now you find out, you need just 3 ints*/
    tmp = realloc(my_array, 3 * sizeof *my_array);
    if(tmp)
    {
    my_array = tmp;
    /*use the array here, it's now just 3 ints long, however, the
    content of the first three ints of the original array are preserved*/
    }
    else
    {
    /*realloc failed, but your allocated 5 ints are still available*/
    }
    }
    else
    {
    /*your request failed, take some sensible action*/
    return EXIT_FAILURE;
    }
    free(my_array);
    return EXIT_SUCCESS;
    }

    HTH
    Robert
    Robert Stankowic, Oct 19, 2003
    #3
  4. On Sun, 19 Oct 2003, James Hu wrote:
    >
    > On 2003-10-19, binaya <> wrote:
    > > Say I allocate a block of memory using the command malloc.I
    > > have a question. Can I deallocate certain portion of it only during
    > > runtime ?

    >
    > If you want to shrink the amount of memory you initially allocated,
    > you can use realloc().


    But you can only shrink it from the front. That is, you can do

    int *p = malloc(5 * sizeof *p); /* allocate 5 ints */

    p = realloc(p, 3 * sizeof *p); /* shrink to only first 3 ints */

    but you absolutely *cannot* do

    int *p = malloc(5 * sizeof *p); /* allocate 5 ints */

    p = realloc(p+2, 3 * sizeof *p); /* shrink to last 3 ints */

    because the pointer 'p+2' didn't come from a call to malloc() --
    only the pointer 'p' itself did. If you want to copy from the
    end of the array, you have to do it explicitly via memcpy() or
    the like:

    int *p, *t;
    p = malloc(5 * sizeof *p);

    t = malloc(3 * sizeof *t);
    memcpy(t, p, 3 * sizeof *t); /* copy last 3 ints into t */
    free(p); /* avoid a memory leak */
    p = t;


    Note that in all the examples above, I left out the proper
    error checking. After each call to malloc or calloc, remember
    to check the returned pointer for NULL:

    int *p;

    p = malloc(n * sizeof *p);
    if (p == NULL)
    printf("Whoops! Out of memory!\n");
    else
    (...)
    free(p);

    And remember that if realloc() returns NULL, the original block
    of memory is *still* *allocated* -- so use a temporary variable!

    int *p, *t;

    p = malloc(n * sizeof *p);
    if (p != NULL) {
    t = realloc(p, k * sizeof *p);
    if (t != NULL)
    p = t;
    else
    printf("No memory for realloc, but p is still valid!\n");
    }
    free(p);


    HTH,
    -Arthur
    Arthur J. O'Dwyer, Oct 19, 2003
    #4
  5. (binaya) wrote:

    Others have already responded; however, one note:

    > Say I allocate 5 pointers to int as below.


    You don't.

    > link=(int*)malloc(5*sizeof(int))


    You allocate memory to hold five ints.

    Consider:

    /* allocate memory for five ints: */
    int *foo;
    foo = malloc( 5 * sizeof *foo );

    /* allocate memory for five pointers to int: */
    int **bar;
    bar = malloc( 5 * sizeof *bar );

    Regards
    --
    Irrwahn
    ()
    Irrwahn Grausewitz, Oct 19, 2003
    #5
  6. binaya wrote:
    > Dear all,
    >
    > Say I allocate a block of memory using the command malloc.I
    > have a question. Can I deallocate certain portion of it only during
    > runtime ?


    If you allocate a block of memory using the function [not 'command']
    malloc, you can resize the allocation with the function realloc.
    Deallocation (for which the function free is used) of part of it is not
    possible.

    > For eg:
    >
    > Say I allocate 5 pointers to int as below.
    >
    > link=(int*)malloc(5*sizeof(int))


    It is better to use a form like
    link = malloc(5 * sizeof *link);
    The cast is useless and can mask errors and the sizeof(int) can bite you
    should the type of link change. In fact, it has already bitten you, since
    you claim that you are allocating 5 pointers to int, while your form
    allocates a space for 5 ints and stores 1 pointer to it in link.

    It would be better, of course, to find a way to turn the literal 5 into a
    symbolic value.


    > But during runtime, I find that I only need the front 3 of them.ie
    > I only need link,link+1 and link+2.


    recapitulation: Then reallocate with realloc.

    > If I don't need link+3 and link+4, can I free these last two
    > pointers to int using the command free(link+3) ?


    recapitulation: No. Reallocate with realloc.

    > If not, then what is the best way to do so ?


    recapitulation: Reallocate with realloc.

    --
    Martin Ambuhl
    Martin Ambuhl, Oct 19, 2003
    #6
  7. binaya

    pete Guest

    binaya wrote:
    >
    > Dear all,
    >
    > Say I allocate a block of memory using the command malloc.I
    > have a question. Can I deallocate certain portion of it only during
    > runtime ?
    >
    > For eg:
    >
    > Say I allocate 5 pointers to int


    > But during runtime, I find that I only need the front 3 of them.


    /* BEGIN new.c */

    #include <stdio.h>
    #include <stdlib.h>

    /**
    #define OPTIONAL
    /*/
    #undef OPTIONAL
    /**/

    #define TOTAL 5
    #define FIRST 3
    #define str(s) # s
    #define xstr(s) str(s)

    int main(void)
    {
    int **pointer, **temp_pointer;
    size_t index, size;

    size = TOTAL;
    do {
    pointer = malloc(size * sizeof *pointer);
    } while (!pointer && --size != 0);
    if (!pointer) {
    fputs("This isn't going to work\n", stderr);
    exit(EXIT_FAILURE);
    }
    putchar('\n');
    for (index = 0; size > index; ++index) {
    pointer[index] = malloc(sizeof *pointer[index]);
    if (!pointer[index]) {
    printf("\nmalloc(sizeof *pointer[index]) "
    "failed allocation attempt %d\n\n", index + 1);
    while (size > ++index) {
    pointer[index] = 0;
    }
    break;
    } else {
    *pointer[index] = index;
    }
    }
    for (index = 0; size > index; ++index) {
    if (pointer[index]) {
    printf("*pointer[%d] is %d\n", index, *pointer[index]);
    } else {
    printf(" pointer[%d] is NULL\n", index);
    }
    }

    #ifdef OPTIONAL
    putchar('\n');
    index = size;
    while(index-- > FIRST) {
    free(pointer[index]);
    pointer[index] = 0;
    }
    for (index = 0; TOTAL > index; ++index) {
    if (pointer[index]) {
    printf("*pointer[%d] is %d\n", index, *pointer[index]);
    } else {
    printf(" pointer[%d] is NULL\n", index);
    }
    }
    #endif

    temp_pointer = pointer;
    pointer = realloc(pointer, FIRST * sizeof *pointer);
    if (pointer) {
    printf("\npointer was reallocated from %d"
    " elements, to " xstr(FIRST) " elements.\n", size);
    index = FIRST;
    while(index--) {
    free(pointer[index]);
    }
    } else {
    pointer = temp_pointer;
    index = TOTAL;
    while(index--) {
    free(pointer[index]);
    }
    }
    free(pointer);
    return 0;
    }

    /* END new.c */

    --
    pete
    pete, Oct 19, 2003
    #7
  8. binaya

    pete Guest

    pete wrote:
    >
    > binaya wrote:
    > >
    > > Dear all,
    > >
    > > Say I allocate a block of memory using the command malloc.I
    > > have a question. Can I deallocate certain portion of it only during
    > > runtime ?
    > >
    > > For eg:
    > >
    > > Say I allocate 5 pointers to int

    >
    > > But during runtime, I find that I only need the front 3 of them.


    > /* BEGIN new.c */


    > size = TOTAL;


    Subsequent appearences of the TOTAL macro should be replaced by "size"

    > for (index = 0; TOTAL > index; ++index) {


    for (index = 0; size > index; ++index) {

    > index = TOTAL;


    index = size;

    > /* END new.c */


    --
    pete
    pete, Oct 19, 2003
    #8
  9. binaya

    pete Guest

    pete wrote:
    >
    > binaya wrote:
    > >
    > > Dear all,
    > >
    > > Say I allocate a block of memory using the command malloc.I
    > > have a question. Can I deallocate certain portion of it only during
    > > runtime ?
    > >
    > > For eg:
    > >
    > > Say I allocate 5 pointers to int

    >
    > > But during runtime, I find that I only need the front 3 of them.

    >
    > /* BEGIN new.c */
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    >
    > /**


    /**/

    > #define OPTIONAL
    > /*/
    > #undef OPTIONAL
    > /**/


    > #ifdef OPTIONAL
    > putchar('\n');
    > index = size;
    > while(index-- > FIRST) {
    > free(pointer[index]);
    > pointer[index] = 0;
    > }
    > for (index = 0; TOTAL > index; ++index) {
    > if (pointer[index]) {
    > printf("*pointer[%d] is %d\n", index, *pointer[index]);
    > } else {
    > printf(" pointer[%d] is NULL\n", index);
    > }
    > }
    > #endif


    Upon further consideration,
    the OPTIONAL part, is really mandatory.
    Whatever you allocate, you should free.

    --
    pete
    pete, Oct 19, 2003
    #9
  10. binaya

    pete Guest

    pete wrote:

    > Upon further consideration,
    > the OPTIONAL part, is really mandatory.
    > Whatever you allocate, you should free.


    /* BEGIN allocation.c */

    #include <stdio.h>
    #include <stdlib.h>

    #define TOTAL 5
    #define FIRST 3
    #define str(s) # s
    #define xstr(s) str(s)

    int main(void)
    {
    int **pointer, **temp_pointer;
    size_t index, size;

    size = TOTAL;
    do {
    pointer = malloc(size * sizeof *pointer);
    } while (!pointer && --size != 0);
    if (!pointer) {
    fputs("This isn't going to work\n", stderr);
    exit(EXIT_FAILURE);
    }
    putchar('\n');
    for (index = 0; size > index; ++index) {
    pointer[index] = malloc(sizeof *pointer[index]);
    if (!pointer[index]) {
    printf("\nmalloc(sizeof *pointer[index]) "
    "failed allocation attempt %d\n\n", index + 1);
    while (size > ++index) {
    pointer[index] = 0;
    }
    break;
    } else {
    *pointer[index] = index;
    }
    }
    for (index = 0; size > index; ++index) {
    if (pointer[index]) {
    printf("*pointer[%d] is %d\n", index, *pointer[index]);
    } else {
    printf(" pointer[%d] is NULL\n", index);
    }
    }
    putchar('\n');
    index = size;
    while(index-- > FIRST) {
    free(pointer[index]);
    pointer[index] = 0;
    }
    for (index = 0; size > index; ++index) {
    if (pointer[index]) {
    printf("*pointer[%d] is %d\n", index, *pointer[index]);
    } else {
    printf(" pointer[%d] is NULL\n", index);
    }
    }
    temp_pointer = pointer;
    pointer = realloc(pointer, FIRST * sizeof *pointer);
    if (pointer) {
    printf("\npointer was reallocated from %d"
    " elements, to " xstr(FIRST) " elements.\n", size);
    index = FIRST;
    while(index--) {
    free(pointer[index]);
    }
    } else {
    pointer = temp_pointer;
    index = size;
    while(index--) {
    free(pointer[index]);
    }
    }
    free(pointer);
    return 0;
    }

    /* END allocation.c */


    --
    pete
    pete, Oct 19, 2003
    #10
  11. binaya

    pete Guest

    pete wrote:

    > int main(void)
    > {
    > int **pointer, **temp_pointer;
    > size_t index, size;


    It's full of bugs.
    The simplest way to fix the printf calls,
    is to declare index and size as type int:

    int **pointer, **temp_pointer, size_t index, size;

    > printf("\nmalloc(sizeof *pointer[index]) "
    > "failed allocation attempt %d\n\n", index + 1);


    > if (pointer[index]) {
    > printf("*pointer[%d] is %d\n", index, *pointer[index]);
    > } else {
    > printf(" pointer[%d] is NULL\n", index);
    > }
    > }


    > if (pointer[index]) {
    > printf("*pointer[%d] is %d\n", index, *pointer[index]);
    > } else {
    > printf(" pointer[%d] is NULL\n", index);
    > }


    > if (pointer) {
    > printf("\npointer was reallocated from %d"
    > " elements, to " xstr(FIRST) " elements.\n", size);
    > index = FIRST;
    > while(index--) {
    > free(pointer[index]);
    > }


    > /* END allocation.c */


    --
    pete
    pete, Oct 19, 2003
    #11
  12. binaya

    James Hu Guest

    On 2003-10-19, Arthur J. O'Dwyer <> wrote:
    > On Sun, 19 Oct 2003, James Hu wrote:
    >>
    >> If you want to shrink the amount of memory you initially allocated,
    >> you can use realloc().

    >
    > But you can only shrink it from the front.


    I initially thought about mentioning something about this, but I thought
    that any such sentence can be misinterpreted, and figured the intention
    of realloc() would be clear to the OP once he/she read the appropriate
    documentation about realloc(). Just looking at the sentence above, it
    is not clear what the sentence means.

    The information in your post is good, but presented a little strangely.
    I think it is much better to just cut to the chase:

    The the first argument to realloc must be a value returned from a
    previous call to malloc(), calloc(), or realloc(), and must not yet
    have been freed by a call to free() or realloc(). If the first
    argument is NULL, it behaves like malloc(). realloc() may return NULL,
    which means the reallocation did not succeed, but the contents of the
    passed in pointer are unchanged.

    But all the above should have been found in the OP's C language
    reference or compiler documentation.

    If I had more time when I initially responded to the poster, I would
    have provided a wrapper function. I have the time now, so:

    static void * shrink_x(void *p, size_t sz, size_t offset, size_t len);

    /*
    * Deallocate the specified range from an allocated object.
    *
    * p - the allocated object
    * sz - size of the allocated object
    * offset - the starting point of the deallocation
    * len - the number of bytes to deallocate
    *
    * Returns 0 if the deallocation fails, otherwise returns a pointer
    * to the shrunken object.
    */
    void *
    shrink(void *p, size_t sz, size_t offset, size_t len)
    {
    if (p == 0) {
    return realloc(p, (offset+len > sz ? offset+len : sz));
    }
    if (offset+len > sz) {
    return 0;
    }
    if (offset+len == sz) {
    return realloc(p, offset);
    }
    return shrink_x(p, sz, offset, len);
    }

    static void *
    shrink_x(void *p, size_t sz, size_t offset, size_t len)
    {
    char buf[len];
    char *q = p;
    void *t;
    memcpy(buf, q+offset, len);
    memmove(q+offset, q+offset+len, sz-offset-len);
    t = realloc(p, sz-len);
    if (t == 0) {
    memmove(q+offset+len, q+offset, sz-offset-len);
    memcpy(q+offset, buf, len);
    }
    return t;
    }

    I'll leave it as an exercise to the reader to find a way to do the
    memory copies without using an extra array.

    -- James
    James Hu, Oct 19, 2003
    #12
    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. Replies:
    5
    Views:
    607
    Matt Wharton
    Dec 9, 2004
  2. Hassan Iqbal
    Replies:
    3
    Views:
    478
    Al Bowers
    Sep 25, 2003
  3. Curley Q.

    freeing allocated memory

    Curley Q., Apr 28, 2004, in forum: C Programming
    Replies:
    7
    Views:
    371
    Sam Dennis
    Apr 30, 2004
  4. Peter
    Replies:
    34
    Views:
    1,916
    Richard Tobin
    Oct 22, 2004
  5. Praetorian

    Freeing memory allocated by another function

    Praetorian, Dec 5, 2007, in forum: C Programming
    Replies:
    6
    Views:
    617
    Praetorian
    Dec 5, 2007
Loading...

Share This Page