using realloc

This is a discussion on using realloc within the C Programming forums, part of the General Programming Boards category; I have smoke blowing outta my ears and a red head! ...I have this BIG problem in getting realloc to ...

  1. #1
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121

    Angry using realloc

    I have smoke blowing outta my ears and a red head! ...I have this BIG problem in getting realloc to give me more memory! ...I have looked everywhere and tried everything, but my output is still the same!

    Here we go: this is a small test program i have written just to get my head around how realloc works! ...basically, when you run the program, I want it to collect arguments from the command line, and read them into memory putting a '\n' between each arg! Simple i think (5 hours ago!) now its just doing my head in! ...well, here is the code....

    Code:
    /* test.c - test program to see how realloc works   *
     * requires: at least 1 arg, of any type, or length */
    
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    int main(int argc, char **argv){
    
      char *ptr;       /* pointer to allocated memory */
      int i = 0;       /* loop counter */
      unsigned int j;  /* loop counter */
      int chars = 0;   /* counts number of chars in memory */
    
      /* make sure there are args */
      if (argc == 0)
        return 1;
    
      /* read the first argv element into memory using malloc */
      ptr = malloc(sizeof(char) * strlen(argv[i]) + sizeof(char));
      
      /* put args into memory, putting a '\n' between each arg */
      for (i = 0; i < argc; i++){
        /* allocate new memory to hold the arg */
        ptr = realloc(ptr, ((sizeof(char) * strlen(argv[i]) + sizeof(char))));
        /* occupy the allocated memory with arg data */
        for (j = 0; j < strlen(argv[i]); j++){
          *ptr = argv[i][j];
          chars++;
          ptr++;
        }
        /* add '\n' char to memory */
        *ptr = '\n';
      }
    
      /* rewind ptr to begining of data and print */
      ptr -= chars;
      for (i = 0; i < chars; i++){
        printf("%c",*ptr);
        ptr++;
      }
      printf("\n");
    
      /* finished! */
      return 0;
    
    } /* main */
    and here is the output:
    Code:
    [root@localhost shell]# ./test
    ./test
    so it works for one argument!

    but then! if you use more than one! BANG!!!

    Code:
    [root@localhost shell]# ./test one
    *** glibc detected *** ./test: realloc(): invalid pointer: 0x090a000e ***
    ======= Backtrace: =========
    /lib/libc.so.6(__libc_realloc+0x2e6)[0x407f15]
    ./test[0x804848e]
    /lib/libc.so.6(__libc_start_main+0xc6)[0x3b6de6]
    ./test[0x8048365]
    ======= Memory map: ========
    00384000-0039e000 r-xp 00000000 fd:00 1327730    /lib/ld-2.3.5.so
    0039e000-0039f000 r-xp 00019000 fd:00 1327730    /lib/ld-2.3.5.so
    0039f000-003a0000 rwxp 0001a000 fd:00 1327730    /lib/ld-2.3.5.so
    003a2000-004c6000 r-xp 00000000 fd:00 1327799    /lib/libc-2.3.5.so
    004c6000-004c8000 r-xp 00124000 fd:00 1327799    /lib/libc-2.3.5.so
    004c8000-004ca000 rwxp 00126000 fd:00 1327799    /lib/libc-2.3.5.so
    004ca000-004cc000 rwxp 004ca000 00:00 0
    00707000-00708000 r-xp 00707000 00:00 0
    007db000-007e4000 r-xp 00000000 fd:00 1327803    /lib/libgcc_s-4.0.0-20050520.so.1
    007e4000-007e5000 rwxp 00009000 fd:00 1327803    /lib/libgcc_s-4.0.0-20050520.so.1
    08048000-08049000 r-xp 00000000 fd:00 1294304    /home/mconway/work/shell/test
    08049000-0804a000 rw-p 00000000 fd:00 1294304    /home/mconway/work/shell/test
    090a0000-090c1000 rw-p 090a0000 00:00 0          [heap]
    b7f96000-b7f97000 rw-p b7f96000 00:00 0
    b7faa000-b7fab000 rw-p b7faa000 00:00 0
    bff95000-bffab000 rw-p bff95000 00:00 0          [stack]
    Aborted
    It is probably something really stupid that i have missed out or something! but any help is much appriciated! ...I want to use realloc in a bigger program i am working on, but at the moment, i am just counting all the chars in all the args and doing one big malloc in one go (because it works!) but i want to use realloc, so i thought i would find out how it works! BIG MISTAKE!!!!

    Thanks for your help people!

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,047
    sizeof(char) is always 1.

    You don't free anything.

    Why are you using realloc()? You re-allocate the same amount of memory that you already got with malloc().
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,047
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You should never assign the return value of realloc to the pointer you're reallocateing directly. If it fails, it will set your pointer to NULL, and you'll lose whatever you had allocated. (Memory leak.) So you should assign the return value to a different pointer first, then test that to make sure it's not NULL, and then make use of it. But that was just what I caught at a glance.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Location
    Stockholm, Sweden
    Posts
    64
    Code:
    if (argc == 0)
        return 1;
    This will never happen, since all programs receive a minimum of one arguments (the name of the program. Or rather, the command used to invoke the program).

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,047
    Quote Originally Posted by kungtotte
    Code:
    if (argc == 0)
        return 1;
    This will never happen, since all programs receive a minimum of one arguments (the name of the program. Or rather, the command used to invoke the program).
    Actually, it's possible. But not very likely.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121
    OK, so basically, i am wasting my time then! if realloc needs a new pointer every time, i cannot put it in a loop and dynamically assign memory to store strings of various lengths in! I will stick to my original idea of counting all the chars in every arg:
    Code:
    for (i = 0; i < argc; i++){
      chars = strlen(argv[i]);
      chars++;             /* for '\n' char */
    } /* loop */
    char *ptr;
    ptr = malloc(chars);
    /* fill memory with data */
    for (i = 0; i < argc; i++){
      for (j = 0; j < strlen(argv[i]); j++){
        *ptr = argv[i][j];
        ptr++;
      }
      ptr++;
      *ptr = '\n'
      x++;
    }
    This way works, so i will leave realloc alone, i don't see the point in realloc unless you know exactly how many times to realloc and the exact times when you want to do it!!!

    Thanks for the help!

  8. #8
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,166
    Code:
      /* read the first argv element into memory using malloc */
      ptr = malloc(sizeof(char) * strlen(argv[i]) + sizeof(char));
      
      /* put args into memory, putting a '\n' between each arg */
      for (i = 0; i < argc; i++){
        /* allocate new memory to hold the arg */
        ptr = realloc(ptr, ((sizeof(char) * strlen(argv[i]) + sizeof(char))));
        /* occupy the allocated memory with arg data */
        for (j = 0; j < strlen(argv[i]); j++){
          *ptr = argv[i][j];
          chars++;
          ptr++;
        }
        /* add '\n' char to memory */
        *ptr = '\n';
      }
    Your problem is here. Firstly, scrap the first allocation, just initialize ptr to NULL. Next, you're only allocating memory for the current arg in your realloc() call. Change it to this:
    Code:
    ptr = realloc(ptr, (ptr ? strlen(ptr) : 0) + strlen(argv[i]) + 2));
    That way you're allocating memory for the current length of the string in ptr plus the length of the next arg you want to store plus 1 for the '\n' plus 1 for the terminating 0.

    Next, simply add this after the realloc() line:
    Code:
    if(!ptr)
      *ptr = 0;
    strcat(ptr, argv[i]);
    strcat(ptr, "\n");
    or
    Code:
    if(!ptr)
      *ptr = 0;
    sprintf(ptr + strlen(ptr), "%s\n", argv[i]);
    Scrap the rest of the loop.

    And as Quzah mentioned, it's best to use a temporary pointer for the return value of realloc() so your already-allocated memory isn't lost in the event of failure.
    Last edited by itsme86; 12-06-2005 at 01:15 PM.
    If you understand what you're doing, you're not learning anything.

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well, if you don't feel like using realloc...
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    int main( int argc, char **argv )
    {
        size_t length, arg;
        char *ptr = NULL;
    
        for( length = arg = 0; arg < argc; arg++ )
        {
            length += ( 1 + strlen( argv[ arg ] ) );
        }
        ptr = calloc( length + 1, 1 );
        if( ptr == NULL )
            return !! printf("So sad!\n");
    
        for( arg = 0; arg < argc; arg++ )
        {
            strcat( ptr, argv[ arg ] );
            strcat( ptr, "\n" );
        }
    
        printf("The args list:\n%s\n", ptr );
        free( ptr );
    
        return 0;
    }
    [edit] What's with all you fast typists today? [/edit]

    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121
    Quote Originally Posted by itsme86
    Your problem is here. Firstly, scrap the first allocation, just initialize ptr to NULL. Next, you're only allocating memory for the current arg in your realloc() call.
    Right, so i have changed the code to this....
    Code:
    /* test.c - test program to see how realloc works   *
     * requires: at least 1 arg, of any type, or length */
    
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    int main(int argc, char **argv){
    
      char *ptr;       /* pointer to allocated memory */
    
      /* make sure there are args */
      if (argc == 0)
        return 1;
    
      ptr = NULL;
    
      /* put args into memory, putting a '\n' between each arg */
      for (i = 0; i < argc; i++){
        /* allocate new memory to hold the arg */
        ptr = realloc(ptr, (ptr ? strlen(ptr) : 0) + strlen(argv[i]) + 2);
        /* occupy the allocated memory with arg data */
        sprintf(ptr + strlen(ptr), "%s\n", argv[i]);
      }
    
      /* PRINT DATA FROM MEMORY */
      
      /* finished! */
      return 0;
      
    } /* main */
    However, how do i record how many chars have been read so i can print whatever is in the allocated memory???

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You're still immediately assigning realloc in a bad way. That aside, um... strlen? That's what you're asking, right? How long is the string of arguments?


    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,166
    However, how do i record how many chars have been read so i can print whatever is in the allocated memory???
    You don't need to. sprintf() automatically puts a '\0' at the end of whatever you're storing so it becomes a string. All you have to do is printf("%s", ptr);

    Your whole loop could look like this:
    Code:
    for(i = 0;i < argc;++i)
    {
      temp = realloc(ptr, (ptr ? strlen(ptr) : 0) + strlen(argv[i]) + 2);
      if(!temp)
      {
        puts("Memory allocation error!");
        free(ptr):
        return 1;
      }
    
      if(!ptr)
        *temp = 0;  // Make empty string on first iteration so strlen() doesn't bomb
      ptr = temp;
      sprintf(ptr + strlen(ptr), "%s\n", argv[i]);
    }
    
    printf("%s", ptr);
    free(ptr);
    A more efficient loop would require you to keep track of the length of the string you're building:
    Code:
    char *ptr = NULL;
    char *temp;
    int len = 0;
    int lendelta;
    int i;
    
    for(i = 0;i < argc;++i)
    {
      lendelta = strlen(argv[i]) + 1;
    
      temp = realloc(ptr, len + lendelta + 1);
      if(!temp)
      {
        puts("Memory allocation error!");
        free(ptr);
        return 1;
      }
    
      ptr = temp;
      sprintf(ptr + len, "%s\n", argv[i]);
      len += lendelta;
    }
    
    printf("%s", ptr);
    free(ptr);
    Last edited by itsme86; 12-06-2005 at 01:25 PM.
    If you understand what you're doing, you're not learning anything.

  13. #13
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121

    You Are A Saint!!!

    Quote Originally Posted by itsme86
    A more efficient loop would require you to keep track of the length of the string you're building:
    Code:
    char *ptr = NULL;
    char *temp;
    int len = 0;
    int lendelta;
    int i;
    
    for(i = 0;i < argc;++i)
    {
      lendelta = strlen(argv[i]) + 1;
    
      temp = realloc(ptr, len + lendelta + 1);
      if(!temp)
      {
        puts("Memory allocation error!");
        free(ptr);
        return 1;
      }
    
      ptr = temp;
      sprintf(ptr + len, "%s\n", argv[i]);
      len += lendelta;
    }
    
    printf("%s", ptr);
    free(ptr);
    Thats amazing!!! ....Perfect! ...just what i have been looking to do for the last god knows how many hours!!!! You have just made my evening that little bit shorter!!! thanks a lot buddy!!!!! V.Much appriciated!!!!

  14. #14
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121
    Is it better programming to use puts when printing an error? or is there no difference from using printf???

    cheers!

  15. #15
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,166
    puts() is a little more efficient since it doesn't try to parse the string like printf() does. If you do printf("this is a message\n"); (which would be equivalent to puts("this is a message");) then printf() first has to walk through the string checking for conversions you might want it to do. Of course, printf() should be used if you need those conversions, like printf("Failed to allocate %d bytes!\n", size);

    fputs("An error happened!\n", stderr); is probably the best method for printing error messages. That way even if the person running the program is redirecting standard output to a file it will spit the error message out to the screen instead of having it end up in the output file.
    If you understand what you're doing, you're not learning anything.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. did i understood right this explantion of realloc..
    By transgalactic2 in forum C Programming
    Replies: 3
    Last Post: 10-24-2008, 07:26 AM
  2. writing a pack-style function, any advices?
    By isaac_s in forum C Programming
    Replies: 10
    Last Post: 07-08-2006, 08:09 PM
  3. segfault on realloc
    By ziel in forum C Programming
    Replies: 5
    Last Post: 03-16-2003, 03:40 PM
  4. Realloc inappropriate for aligned blocks - Alternatives?
    By zeckensack in forum C Programming
    Replies: 2
    Last Post: 03-20-2002, 01:10 PM
  5. realloc realloc realloc
    By Linette in forum C++ Programming
    Replies: 4
    Last Post: 01-19-2002, 08:18 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21