Thread: malloc casting - quote from the FAQ

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    84

    malloc casting - quote from the FAQ

    Hi all,

    This is a quote from the FAQ about casting malloc.

    "Many still prefer to cast malloc because they feel it makes the intentions of the memory allocation more clear. There is nothing wrong with this except in the event that stdlib.h, the header which declares malloc, is not included. If the return of malloc is cast then the error which would be flagged is hidden"

    I don't understand what can go wrong if I cast malloc return without using stdlib.h, until now I always cast it and I didn't use stdlib.h and everything always work fine, can someone please explain it to me?

    Another thing, which one of the following is the preffered header file for malloc:
    stdlib.h
    alloc.h
    malloc.h
    What is the difference between them and why should I preffer one on the other.

    Your help is apprichiated,
    Many thanks

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The function will be expected to return int if no prototype is found which is obviously wrong because malloc returns void* and C by default allows you to call functions that has no prototype or declaration; thus causing a warning that's masked by your cast.
    This means that the result is undefined. Very bad.
    Therefore, don't cast malloc and let the compiler complain if you haven't included a proper header. It's because of this reason that I always treat warnings as errors in C - you can actually use a function without a proper declaration first.
    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
    Dec 2007
    Posts
    84
    Quote Originally Posted by Elysia View Post
    The function will be expected to return int if no prototype is found which is obviously wrong because malloc returns void* and C by default allows you to call functions that has no prototype or declaration; thus causing a warning that's masked by your cast.
    This means that the result is undefined. Very bad.
    Thank you for your fast reply, I still don't understand something.
    Why is the result is undefined when I cast the return value?
    I thought that casting the result is what defines it.
    For example I will excpect that the following code will be undefined if stdlib.h is not in included:
    Code:
    char *pStr;
    pStr=malloc(sizeof(char)*10);
    Because we didn't include stdlib.h as you said the compiler will assume that the return value is an int.
    But if I cast it, it's not suppose to append because I am telling the compiler the desire return value. Please correct again if I'm wrong.

    Many thanks

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    835
    Normally one doesn't even need a cast on malloc() to tell what type of array is being allocated - there's usually a sizeof(type) expression in malloc()'s argument and you can see from that what the type is. The only time the sizeof() might not be there is if the type is signed or unsigned char, which is guaranteed to have size 1, but even then one could put the sizeof() there anyway, as the compiler will just optimize it out.

    Also, the headers alloc.h and malloc.h are nonstandard. Use the standard stdlib.h.

    Edit: Some people use an expression such as sizeof(*p) instead of sizeof(int), where p is pointer to int, for example. This has the advantage that one can change the type of the array without having to change the malloc() expression at all, although you can't see at a glance what the type is anymore. Whether this is a good idea depends on how likely you think it is that the type might be changed.

    Example: replace
    Code:
    p = malloc(sizeof(int)*10);
    with
    Code:
    p = malloc(sizeof(*p)*10);
    Last edited by robatino; 12-17-2007 at 01:40 PM.

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    There's more than just the return type for a function, too, of course. And below C is assembly. The compiler generates assembly and the prototype of a function defines how the compiler must generate code. If the compiler can't find a function or prototype, then it will have to guess. What parameters are passed to the function? What's the calling convention? What does it return?
    If you cast the result of malloc to something, possibly other than void* and the function isn't found, then the compiler will guess in generating the code. And there's no standard saying how the code should be generated either.
    There's not even something saying that eax must be used for return. So if you it to char*, the compiler might use another register to pass the return type (or check for return type), but the actual function might store the result in eax, because it's 4 bytes - a pointer.
    As I mentioned, the the result is undefined.

    And what if a function takes more than one argument, possibly an optional one? The compiler won't pass it and the stack will contain one less parameter than expected by the function and thus may result in a crash. The same goes if the function uses another calling convention that your standard one you're using for your project - might result in another crash.
    Many bad things can happen and that's why it's bad.
    Last edited by Elysia; 12-17-2007 at 01:23 PM.
    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.

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by salvadoravi View Post
    Thank you for your fast reply, I still don't understand something.
    Why is the result is undefined when I cast the return value?
    The cast is not undefined. The cast potentially masks the error of failing to include stdlib.h. If you fail to include stdlib.h, calls to malloc() are undefined.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ok, if we start with the simple case that we have a 64-bit machine, which uses "int" as a 32-bit value. We write:
    Code:
    char *p = (char *)malloc(sizeof(*p) * 1000);
    If we don't include a header for malloc [1] then the return type of malloc will be assumed to be int. Since the int only uses the lower 32 bits of the register, the value is extended to 64 bits by some means (filling with zeros or sign-extending). The result is a pointer that can only reach +/- 2GB or 4GB in the system. This will work just fine until your memory allocation reaches ABOVE this limit [which may be immediately or at a later stage]. What that limit is breached, the result will most likely be a crash, but if you are really unlucky, it will modify some other memory instead!

    Another example would be on a 68000-based machine, where a different register (A0) is used for returning pointers than the register used for integer value returns (D0). So the compiler will, if you use a cast and don't include stdlib.h, use D0 instead of A0. There's really no guessing on what the value in D0 is, so it's definitely undefined.

    --
    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.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Eh? Two of the exactly same posts almost 40 minutes after each other?
    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
    Registered User
    Join Date
    Dec 2007
    Posts
    84

    Why is it working??

    Guys thank you for your quality words.
    I still don't understand 1 thing.

    If I don't include stdlib.h so my compiler make assumption about malloc because it doesn't see a definition or prototype.
    I will get the following warnings:
    warning C4013: 'malloc' undefined; assuming extern returning int
    warning C4047: '=' : 'int *' differs in levels of indirection from 'int '

    Until now it all make sense, but how come that the following code is working without knowing what malloc do?
    Code:
    #include <stdio.h>
    
    int main(void)
    {
      int *pNumbers;
      int i;
    
      pNumbers=malloc(1000*sizeof(*pNumbers));
      if (pNumbers==NULL)
      {
    	puts("Not enough memory!");
    	return 1;
      }
    
      for (i=0;i<1000;++i)
    	pNumbers[i]=i;
    
      for (i=0;i<1000;++i)
    	printf("%d\n",pNumbers[i]);
    
      return 0;
    }
    If malloc is unknown function why after running the code I do get a memory allocation as expected from it?

    thank you again!

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    Eh? Two of the exactly same posts almost 40 minutes after each other?
    Not any more, and my browser wasn't responding, so I clicked "submit" again, only to then realize there was two posts on the same subject - I went away from the computer for a while in between - I don't normally sit 40 minuts to wait for it to respond [unless I really expect it to take 40 minuts to complete, of course].

    --
    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.

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by salvadoravi View Post
    Until now it all make sense, but how come that the following code is working without knowing what malloc do?
    Undefined behavior means anything can happen. "Anything" includes working properly. It could stop working properly for any reason, though.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by salvadoravi View Post
    If malloc is unknown function why after running the code I do get a memory allocation as expected from it?

    thank you again!
    The compiler doesn't know about the function, but the linker finds it and makes a call to it, thus malloc is executed and returned, but the effect is still undefined and may vary from compiler to platform - you aren't guaranteed to get the same result!
    Now, if you do it right, however, you will get the right result because the operation is defined. If it doesn't work right, then it's a compiler (or linker) bug, most likely.
    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.

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Let met guess: sizeof(int) == sizeof(int *) on this machine? And unless it's a machine that uses different registers for pointers and integers, yes, it will work OK.

    Try it on a 64-bit machine, making sure you allocate enough memory to fill at least 2GB, and you'll have a different story.

    --
    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.

  14. #14
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Maybe someone should update the FAQ with some of this info. From what I read on the FAQ, I never knew that casting malloc() could be this disasterous.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > but how come that the following code is working without knowing what malloc do?
    Like a piece of metal, how many times do you think you can bend it before it breaks?

    Sure it seems easy enough at first, but sooner or later your luck will run out and the metal will snap in two. If you're at 30,000 ft when that happens, the result ain't pretty.

    Writing programs is about being right all the time, not about how much I can remove from the code and still make it work on the current machine.
    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. Wiki FAQ
    By dwks in forum A Brief History of Cprogramming.com
    Replies: 192
    Last Post: 04-29-2008, 01:17 PM
  2. malloc, calloc from the FAQ
    By salvadoravi in forum C Programming
    Replies: 10
    Last Post: 01-21-2008, 03:29 AM
  3. FAQ: Difference between C and C++ style casting
    By Queatrix in forum FAQ Board
    Replies: 1
    Last Post: 12-23-2006, 12:09 PM
  4. FAQ: Casting malloc?
    By Simon in forum FAQ Board
    Replies: 44
    Last Post: 10-08-2002, 02:25 AM
  5. Casting malloc?
    By Simon in forum C Programming
    Replies: 44
    Last Post: 10-08-2002, 02:25 AM