Thread: memory allocation

  1. #1
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115

    Question memory allocation

    I was wondering if anyone can give me an answer to this:
    Here is the code

    int main(int argv, char *argc[])
    {
    char **name;
    char *tempstring = "this string"

    name = (char**)malloc(sizeof(char**) * NoOfInFiles))

    for(i=0;i<NoOfFile;i++)
    name[i] = strdup(tempstring);

    // Do other stuff

    free(name);
    return(0);
    }

    ok now my question is this:
    If the memory for name is freed, will it free the memory that has been allocted by strdup() or will that memory still be set aside?
    The way I think it works is that I would have to do this first :

    for(i=0;i<NoOfFiles;i++)
    free(name[i]);

    before freeing name? is this right or am I just messed up?
    And the pointer to pointer has to stay. It is too deep in the original code to remove it.
    any help would be appreciated
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  2. #2
    The Artful Lurker Deckard's Avatar
    Join Date
    Jan 2002
    Posts
    633
    This is a memory leak.

    strdup() uses malloc to allocate memory for the duplicate string. When you call free( name );, you are deallocating the memory for the pointers that name points to, but you are not deallocating the memory strdup() set aside for the individual strings.
    Jason Deckard

  3. #3
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    What's wrong with this picture?
    Code:
    name = (char**)malloc(sizeof(char**) * NoOfInFiles)) 
    
    for(i=0;i<NoOfFile;i++)
    It's the empty line in between malloc and the start of your loop. Nowhere do you test to see if malloc failed, always test malloc, always.
    Code:
    name = (char**)malloc(sizeof(char**) * NoOfInFiles)) 
    if ( name != NULL ) {
      for(i=0;i<NoOfFile;i++) 
      /* The rest of your code */
    }
    else {
      /* Handle the error */
    }
    There are also two problems with this line, not true errors but they have the potential for annoyance.

    name = (char**)malloc(sizeof(char**) * NoOfInFiles))

    In C, you aren't required to cast malloc, and it's usually best not to because if you cast the result of malloc then that could hide an error, such as forgetting to include stdlib.h. You also make malloc type specific this way when you could write it much more maintenance friendly.

    name = malloc( NoOfInFiles * sizeof **name )

    This saves you the trouble of having to change several instances of char ** because malloc is no longer bound to the type of the variable that it is allocating memory for. If you change name to int then you don't have to change the above line at all.

    -Prelude
    My best code is written with the delete key.

  4. #4
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    Thanks for the help. I know I didn't check malloc. I didnt intend to... this is crap code..just example and I just omitted checking for convience. As for the cast, that is the way a teacher showed our class how to do it. Actually come to think of it, every teacher I had for C told us to cast malloc. I do however see your point
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  5. #5
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >every teacher I had for C told us to cast malloc
    I hate to say it, but your teachers were all wrong. In older C malloc was required to be cast because of how the generic pointer ( char * or void * depending on how far back you go ) behaved of which I'll not bore you, but under the ANSI/ISO C89 standard casting is optional and considered a bad practice for the reasons I stated earlier.

    -Prelude
    My best code is written with the delete key.

  6. #6
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    you wont bore me with history... I find the history of C quite interesting. It wouldn't surprise me to know my teachers were wrong. Seems like they will hire anyone to teach. My advanced C teacher didn't know squat about manipulating bit or how to access hardware but she could make a linked list ..... lol
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  7. #7
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >but she could make a linked list
    Sad, but often true. Teachers tend to be one step ahead of the students if you're lucky. Very few instructors are knowledgeable, if they were then they would have high paying jobs and wouldn't need to teach.

    >I find the history of C quite interesting
    void * only made it into C with the ANSI standard, before that the char * played the role of generic pointer that void * now enjoys and because of a more strict pointer to pointer conversion rule, you had to cast from a generic pointer to anything else before using it, even in assignment. The ANSI standard changed the rule a bit for assignment in that pointers could be assigned to and from void * and compared with them without the use of an explicit cast. Though other pointer to pointer conversions still require you to cast them.

    All very interesting if you have the time to figure it out, K&R offers a good explanation of pointer casting and rules in section A6.6 of the reference.

    -Prelude
    My best code is written with the delete key.

  8. #8
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    Thanks for that bit of info Prelude. I read about the change from char* to void* but I didnt know about the cast being dropped. I will have to go read me bible again.
    As for the code here is something interesting to chew on.
    I dropped the cast like you said to do and i get this error:

    error C2440: '=' : cannot convert from 'void *' to 'char ** '
    Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    Error executing cl.exe.

    this is the code in question
    if(!(name = malloc(sizeof(char**) * NoOfInFiles)))
    {
    printf("memory error\n");
    exit(1);
    }

    that is when I reallized that I was using a .cpp file extension so I changed it to .C and there we go, it compiles without a complaint. Seems to me that c++ changed this to require an explicit cast. I know this is a C board but though you might find it interesting if you code in both languages(even though I should be using the new operator in C++ anyways).

    I also tested this
    for(i=0;i<NoOfInFiles;i++)
    {
    printf("Freeing %s\n",name[i]);
    free(name[i]);
    }
    and it worked fine, so I got that solved at least.
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  9. #9
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >that is when I reallized that I was using a .cpp file extension
    That's one of the traps that C programmers fall into with C++, C doesn't require explicit casts yet C++ does. That's also one of the reasons C++ programmers who migrate to C use explicit casts.

    Sometimes it's hard to think of C and C++ as two completely different languages. The syntax is similar but there are some subtle differences since C++ and C both evolved after C++ was created as a superset of C.

    -Prelude
    My best code is written with the delete key.

  10. #10
    Sayeh
    Guest
    At this stage, as a C programmer, the only reason to continue coercing functions like malloc() to the desired type, is for backward compatability with older compilers.

    And, just an aside, I've never understood why the new generation of programmers use the term 'casting' all the time-- which came from the C++ genre of thinking... It is called 'type coercion'.

    Maybe people couldn't say the second word-- it's pronounced ('ko - UR - zhun').

    enjoy.

  11. #11
    The Artful Lurker Deckard's Avatar
    Join Date
    Jan 2002
    Posts
    633
    Originally posted by Sayeh
    It is called 'type coercion'.
    Type conversion (K&R Section 2.7)

    I suspect the reason C programmers use the term casting when they mean type conversion is also due to K&R, which seems to use the phrases interchangeably. In fact, the index of K&R (second edition) has this to say:
    • type conversion operator, see cast


    [edit]
    It should be noted that the terms 'type conversion' and 'cast' are not interchangeable. A type conversion is done automatically, whereas a cast is explicit.
    Code:
    int i;
    char c;
    
    c = i; /* type conversion */
    c = (char) i; /* cast */
    I'll admit this seems a little anal, but my original post did not make this clear :)
    [/edit]
    Last edited by Deckard; 03-15-2002 at 11:40 AM.
    Jason Deckard

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory allocation question
    By dakarn in forum C Programming
    Replies: 11
    Last Post: 12-01-2008, 11:41 PM
  2. Dynamic memory allocation.
    By HAssan in forum C Programming
    Replies: 3
    Last Post: 09-07-2006, 05:04 PM
  3. Dynamic memory allocation...
    By dicorr in forum C Programming
    Replies: 1
    Last Post: 06-24-2006, 03:59 AM
  4. C memory allocation to c++
    By markucd in forum C++ Programming
    Replies: 2
    Last Post: 11-30-2005, 05:56 AM
  5. Understanding Memory Allocation
    By Ragsdale85 in forum C Programming
    Replies: 7
    Last Post: 10-31-2005, 08:36 AM