C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 12-17-2007, 12:36 PM   #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
salvadoravi is offline   Reply With Quote
Old 12-17-2007, 12:44 PM   #2
Mysterious C++ User
 
Elysia's Avatar
 
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:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.
Elysia is offline   Reply With Quote
Old 12-17-2007, 01:15 PM   #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
salvadoravi is offline   Reply With Quote
Old 12-17-2007, 01:21 PM   #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);
with
Code:
p = malloc(sizeof(*p)*10);

Last edited by robatino; 12-17-2007 at 01:40 PM.
robatino is offline   Reply With Quote
Old 12-17-2007, 01:21 PM   #5
Mysterious C++ User
 
Elysia's Avatar
 
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:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.

Last edited by Elysia; 12-17-2007 at 01:23 PM.
Elysia is offline   Reply With Quote
Old 12-17-2007, 01:36 PM   #6
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,762
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.
brewbuck is online now   Reply With Quote
Old 12-17-2007, 03:24 PM   #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);
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.
matsp is offline   Reply With Quote
Old 12-17-2007, 04:05 PM   #8
Mysterious C++ User
 
Elysia's Avatar
 
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:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.
Elysia is offline   Reply With Quote
Old 12-17-2007, 04:11 PM   #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!
salvadoravi is offline   Reply With Quote
Old 12-17-2007, 04:12 PM   #10
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
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.
matsp is offline   Reply With Quote
Old 12-17-2007, 04:14 PM   #11
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,762
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.
brewbuck is online now   Reply With Quote
Old 12-17-2007, 04:15 PM   #12
Mysterious C++ User
 
Elysia's Avatar
 
Join Date: Oct 2007
Posts: 14,783
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.
__________________
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:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.
Elysia is offline   Reply With Quote
Old 12-17-2007, 04:24 PM   #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   Reply With Quote
Old 12-17-2007, 04:26 PM   #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   Reply With Quote
Old 12-17-2007, 04:44 PM   #15
and the hat of Jobseeking
 
Salem's Avatar
 
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.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

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


All times are GMT -6. The time now is 09:31 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

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