Re: Trouble with malloc().

From: Artie Gold (artiegold_at_austin.rr.com)
Date: 11/24/03


Date: Sun, 23 Nov 2003 23:09:57 GMT

Kevin Goodsell wrote:
> Pegboy wrote:
>
>> I am having trouble with malloc() again for a PC app I am developing. The
>> method of the suspicious line of code seems to be Ok on a embedded
>> platform,
>> but not with the PC platform. The embedded platform uses a different
>> compiler. I feel like I'm overlooking a very simple problem, but I can't
>> see it. I would appreciate any help. Thank you.
>>
>> I am trying to allocate memory for a structure of type NAT_S which
>> contains
>> a pointer to a structure of type NAT_ENTRY_S (see code below).
>>
>> The compiler reports warning 'Suspicious pointer conversion' as indicated
>> below in the code. This is the only warning or error I get.
>>
>> This code appears to work but the next call to malloc() following
>> this, the
>> app crashes. In some instances, ReadNat() is not called and the app works
>> Ok. So the problem points to within ReadNat(), which is where the warning
>> is.
>>
>> I examined/watched the address given to 'nat' and 'nat->entries' and they
>> are different by 24 bytes when they should be different by 6. The sizeof(
>> NAT_S ) is 6.
>>
>> /************************************************************/
>> typedef struct
>> {
>> short a;
>> short b;
>> long c;
>> long d;
>> } NAT_ENTRY_S;
>>
>> typedef struct
>> {
>> short num_entries;
>> NAT_ENTRY_S *entries;
>> } NAT_S;
>>
>> NAT_S *ReadNat( FILE *file, long offset )
>> {
>> NAT_S *nat;
>> short i, num_entries;
>>
>> fseek( file, offset, SEEK_SET );
>> num_entries = ReadShort( file );
>>
>> if( (nat = malloc( sizeof( NAT_S ) + (num_entries * sizeof(
>> NAT_ENTRY_S )) )) != NULL )
>> {
>> nat->num_entries = num_entries;
>> nat->entries = nat + sizeof( NAT_S ); /* COMPILER WARNING:
>> Suspicious pointer conversion */
>
>
> I'll say it's suspicious. It's also most likely the cause of your
> problem. What makes you think that nat + sizeof(NAT_S) yields a memory
> address that will be properly aligned for a NAT_ENTRY_S? You cannot
> simply place an object anywhere in memory that is convenient. Some
> objects in some implementations must be aligned on certain boundaries
> (e.g., a 4-byte integer might be required to start on an address that is
> divisible by 4).

Though alignment *may* be an issue here (practically speaking,
however, I doubt it) -- the problem is deeper. The value of the
expression:

nat + sizeof( NAT_S )

is equivalent to:

&(nat[sizeof(NAT_S)])

(probably not what you want) which is then assigned to a
not-necessarily-compatible pointer type. [Remember, pointer
arithmetic is performed in units of the size of the type of the
object to which a pointer points.]

I would recommend to the OP to turn up the warning levels as high as
possible. This would reveal the *real* problem.

>
> malloc() is required to return a pointer to memory that is properly
> aligned for any type, but that address plus some arbitrary value is NOT
> required to yield a pointer to memory that is properly aligned for some
> random type.
>
> -Kevin

HTH,
--ag

-- 
Artie Gold -- Austin, Texas
Oh, for the good old days of regular old SPAM.