Thread: the basics of malloc

  1. #1
    Registered User
    Join Date
    May 2008
    Location
    Kentucky
    Posts
    13

    the basics of malloc

    I've enjoyed many of your posts and decided to register and pick your minds if you don't mind.

    Somehow I've managed to program for a LONG time and never bothered to understand some things. All too often I've done "just make it work" programming.

    I'm working on a program now and noticing things I just think I should understand. For example, here's a line from a program:

    note[ctr].nBody = (char *) malloc (100 * sizeof( char ) ) ;

    The structure for note is:
    Code:
    typedef char *STRING
    
    typedef struct noteinfo {	       /* structure of note		*/
    	int    nSize;				/* number of characters in note body	*/
    	STRING nBody;	 		  /* text of note					*/
    	STRING nExtra;			  /* area for extra info such as date string	*/
    } NOTEINFO;
    So, later when I'm ready to write the file I wanted to test the note body (note[ctr].nBody) to see if it was empty. I expected to be able to see if it was empty by using

    Code:
    if( note[ctr].nBody == NULL )
    But it turns out that there are four chars in .nBody even though I've done nothing with it since the malloc and sizeof() also returns a size of 4.

    Can anyone tell me what malloc puts in the string during malloc? And, how might I test note[ctr].nBody to see if it is empty? (Empty meaning nothing has been done to it since the malloc.) I've tested for content using lstrlen(), which returns 0. But that seems kinda sloppy.

    Thanks,
    Dale L

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Using sizeof on a pointer will typically return 4 or 8, depending on the size of a pointer on the system. So in other words, you are getting the size of the pointer, and not the actual value or data stored there.
    But if you do sizeof(*nBody), you will get 1 ( sizeof(char) ), because the compiler cannot know how many elements or how big the data block pointed to by the pointer is.
    Malloc only returns NULL if it fails, so you can't check for NULL either.
    Therefore, the better solution is to keep track of whether or not something has been written. But you do have a "nSize" variable, so use that (ie nSize == 0).

    Also beware that typedefing a pointer may not be the greatest idea. It will probably introduce confusion, so avoid that.
    And "n" isn't a typical prefix for a string. It's more of a prefix for numbers.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    May 2008
    Location
    Kentucky
    Posts
    13
    Elysia, thank you. As I read your reply I was banging my head and saying "I knew that." All too often I get caught in the act of thinking content or value rather than pointer. This probably comes from the many years (most of my first ten years of programming) of writing in REXX which is so forgiving that you rarely use pointers.

    Thanks.

    Now, I'll have to figure out a good way to phrase my questions on win32's WriteFile function when using structures. I remember quite quickly concluding "this is nuts" and going right back to fopen and fwrite and fputs and the likes.

    Dale L

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    But fopen/fwrite are C standard functions, WriteFile is not. You would be sacrificing portability.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    May 2008
    Location
    Kentucky
    Posts
    13
    Elysia, agreed. Hence my copies of K&R and Petzold are pretty much resident on my desk. Going through Petzold it is obvious that he is trying to remain win32 compliant. So one day I get to playing with WriteFile and seems that things blow up.

    For example, from the structure in the code above. Lets say I have

    NOTEINFO note[NumberOfNotes] ;

    NumberOfNotes may be pretty much any number: lets say 25.

    Now, I want to drop all 25 of the notes to file using WriteFile. I remember playing with it for quite a while and got unexpected results. Probably forgot about pointers again.

    It would seem that there would be a nice quick and easy one liner to write the 25 notes to file. Any chance you have that one liner on the tip of your tongue?

    Dale L

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    For C:
    fwrite(note, sizeof(note), 1, f);

    Only works if note is defined in the same function where you write the file. Otherwise you're going to have to do something like:
    fwrite(note, sizeof(*note) * num, 1, f);
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    May 2008
    Location
    Kentucky
    Posts
    13
    Elysia, yes. Thanks. I've got it all working in standard C routines. I was curious as to how it would be done with win32's WriteFile. I pulled the following line from some old code that didn't work:

    WriteFile (hFile, note[ctr], sizeof(note[ctr]), &dwBytesWritten, NULL) ;

    Don't knock yourself out on this one. Just toying with things that I've done in the past in, perhaps, far less than professional style.

    Dale L

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Try this instead:
    Code:
    WriteFile (hFile, note, sizeof(note), &dwBytesWritten, NULL) ;
    It's basically the same as the C code.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Bear in mind that writing a struct that contains pointers to a binary file is pretty useless, because if when you load the data next time, the pointers will not be valid [1]. You need to either:
    1. Use fixed length strings in your note data.
    This is by far the easiest to implement.

    2. Write the data out in a different way (so you store the string pointed to by the pointer, rather than the pointer itself).
    This is trickier, but also more flexible as it copes with any length body/extra, as you have to know how much data you have to read, so you first read the nSize, then allocate nSize bytes for nBody, and read nSize bytes into your new pointer, and finally you need to know the length of nExtra and do the same thing there.

    [1] Of course, if you don't de-allocate the memory (or exit the application), it will still be valid if when you read it back - but the point of storing something is usually that you want to exit the application and then read it back when you start the application again.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Registered User
    Join Date
    May 2008
    Location
    Kentucky
    Posts
    13
    Thanks for the input. While the WriteFile line I gave was not quite a real life example, your comments certainly did help shake the cobwebs and clear things up. Thanks.

    Now, if you don't mind, another concern.

    Somewhere I've read that after doing a malloc (or alloc) it is good to set the variable value to NULL such as:

    Code:
    note[ctr].nBody = malloc (300 * sizeof( char ) ) ;
    note[ctr].nBody = NULL ;
    Okay, that kinda makes sense. As I understand, it would leave the var pointing to nothing. Would this be done to help in the area of memory leaks? Is this a good practice? Would I really want to bother setting to NULL if I'm actually going to fill the nBody immediatly after the malloc?

    Thoughts are appreciated.

    Dale L

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yes, it's a good practice. However, you must free it first, otherwise you get a memory leak.
    It allows you to see if it's a valid pointer or not, which is why it's such a good thing.
    Don't do it right after malloc (your memory you just allocated will be lost!).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    May 2008
    Location
    Kentucky
    Posts
    13
    Let me make sure I understand: setting it to NULL will actually defeat the malloc? So if I set nBody to NULL before doing anything with it I would be defeating the malloc?

    In other words, I would want to first do malloc on nBody and then not until after done using nBody, I would free it and then set it to NULL?

    Dale L

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yes to first and second.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Somehow I've managed to program for a LONG time and never bothered to understand some things. All too often I've done "just make it work" programming.

    it's pointless to program in a language you don't understand so well. you will spend a lot of time debugging problems that would have never been an issue had you just consulted a good C programming book.

    >> Okay, that kinda makes sense. As I understand, it would leave the var pointing to nothing. Would this be done to help in the area of memory leaks? Is this a good practice? Would I really want to bother setting to NULL if I'm actually going to fill the nBody immediatly after the malloc?

    seriously.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    note[ctr].nBody = malloc (300 * sizeof( char ) ) ;
    Now do something with your 300 chars.

    Then when you're done, you do this.
    Code:
    free( note[ctr].nBody );
    note[ctr].nBody = NULL ;
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. malloc + segmentation fault
    By ch4 in forum C Programming
    Replies: 5
    Last Post: 04-07-2009, 03:46 PM
  2. Is there a limit on the number of malloc calls ?
    By krissy in forum Windows Programming
    Replies: 3
    Last Post: 03-19-2006, 12:26 PM
  3. Malloc and calloc problem!!
    By xxhimanshu in forum C Programming
    Replies: 19
    Last Post: 08-10-2005, 05:37 AM
  4. malloc() & address allocation
    By santechz in forum C Programming
    Replies: 6
    Last Post: 03-21-2005, 09:08 AM
  5. malloc always setting length of 8?
    By Zarkhalar in forum C++ Programming
    Replies: 7
    Last Post: 08-01-2004, 11:36 PM