![]() |
| | #1 |
| Registered User Join Date: Dec 2007
Posts: 84
| malloc casting - quote from the FAQ 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 |
| salvadoravi is offline | |
| | #2 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,783
| 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.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #3 | |
| Registered User Join Date: Dec 2007
Posts: 84
| Quote:
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); 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 | |
| salvadoravi is offline | |
| | #4 |
| Registered User Join Date: Sep 2006
Posts: 837
| 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); Code: p = malloc(sizeof(*p)*10); Last edited by robatino; 12-17-2007 at 01:40 PM. |
| robatino is offline | |
| | #5 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,783
| 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.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
Last edited by Elysia; 12-17-2007 at 01:23 PM. | |
| Elysia is offline | |
| | #6 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,762
| 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. |
| brewbuck is online now | |
| | #7 |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| 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); ![]() 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. |
| matsp is offline | |
| | #8 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,783
| Eh? Two of the exactly same posts almost 40 minutes after each other?
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #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;
}
thank you again! |
| salvadoravi is offline | |
| | #10 | |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| Quote:
-- 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. | |
| matsp is offline | |
| | #11 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,762
| |
| brewbuck is online now | |
| | #12 | ||
| Mysterious C++ User Join Date: Oct 2007
Posts: 14,783
| Quote:
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.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System I dedicated my life to helping others. This is only a small sample of what they said: "Thanks Elysia. You're a programming master! How the hell do you know every thing?" Quoted... at least once. Quote:
| ||
| Elysia is offline | |
| | #13 |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| 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. |
| matsp is offline | |
| | #14 |
| and the hat of sweating Join Date: Aug 2007 Location: Toronto, ON
Posts: 3,279
| 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. |
| cpjust is offline | |
| | #15 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,676
| > 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. |
| Salem is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Wiki FAQ | dwks | General Discussions | 192 | 04-29-2008 01:17 PM |
| malloc, calloc from the FAQ | salvadoravi | C Programming | 10 | 01-21-2008 03:29 AM |
| FAQ: Difference between C and C++ style casting | Queatrix | FAQ Board | 1 | 12-23-2006 12:09 PM |
| FAQ: Casting malloc? | Simon | FAQ Board | 44 | 10-08-2002 02:25 AM |
| Casting malloc? | Simon | C Programming | 44 | 10-08-2002 02:25 AM |