Different sizes of data and function pointers on a machine -- void* return type of malloc, calloc, and realloc

  • Follow


In reference with the below code,

#include <stdlib.h>
#include <stdio.h>

int f(void)
{
    printf("\n In f . . . \n");
}

int main(void)
{
    int (*p)(void) =3D malloc(sizeof(int (*)(void)));
   =20
    return 0;    =20
}

I would like to question about the return type of malloc(calloc, and reallo=
c).

Assume that the above code runs on a machine wherein the data pointers and =
function pointers are of different sizes. Then, what malloc returns is a fu=
nction pointer but after casting it to void* while returning(Or, after assi=
gning it to a void* variable internally and returning its value).

Now, isn't malloc giving us the truncated address in the above context? Con=
sider the same question applicable to calloc and realloc when used in such =
a context.

Cheers,
Raghavan Santhanam





=20
0
Reply raghavanil4m (37) 6/25/2012 4:08:28 PM

On Jun 25, 5:08=A0pm, Myth__Buster <raghavani...@gmail.com> wrote:

> Assume that the above code runs on a machine wherein the data pointers an=
d function pointers are of different sizes. Then, what malloc returns is a =
function pointer but after casting it to void* while returning(Or, after as=
signing it to a void* variable internally and returning its value).
>
> Now, isn't malloc giving us the truncated address in the above context? C=
onsider the same question applicable to calloc and realloc when used in suc=
h a context.

malloc always returns a data pointer. You can ask it to return a data
pointer to some memory area that is big enough to hold a function
pointer, but it will still be a data pointer.

Maybe the situation would be less confusing to you if you first
declare a struct with a single member that is a function pointer, then
use malloc to return a data pointer pointing to one such struct.
0
Reply christian.bau1 (403) 6/25/2012 4:16:07 PM


On 06/25/2012 12:08 PM, Myth__Buster wrote:
> In reference with the below code,
> 
> #include <stdlib.h>
> #include <stdio.h>
> 
> int f(void)
> {
> printf("\n In f . . . \n");
> }
> 
> int main(void)
> {
> int (*p)(void) = malloc(sizeof(int (*)(void)));

"The pointer returned if the allocation succeeds is suitably aligned so
that it may be assigned to a pointer to any type of object ..."
(7.22.3p1). Note carefully that this only applies to pointers to object
types, not function types.

The code above converts a pointer to void into a pointer to a function
type. The behavior of this code is well-defined if malloc() fails,
because 6.3.6.2p4 says "Conversion of a null pointer to another pointer
type yields a null pointer of that type." However, the behavior of this
code is undefined if malloc() returns a non-null pointer "by omission of
any explicit definition of the behavior" (4p2). The only other
conversion defined by the standard that involves function pointer types
is the conversion from one function pointer type to another (6.3.6.3p8),
which doesn't apply here.

> return 0;
> }
> 
> I would like to question about the return type of malloc(calloc, and
> realloc).

All three functions behave the same, as far as the issue raided by your
message is concerned.

> Assume that the above code runs on a machine wherein the data
> pointers and function pointers are of different sizes. Then, what
> malloc returns is a function pointer ...

That's incorrect - what gave you that idea? The rest of your message
depends upon that misconception, so I'll just stop here.
0
Reply jameskuyper (5170) 6/25/2012 4:52:22 PM

On Monday, June 25, 2012 9:16:07 AM UTC-7, christian.bau wrote:
> On Jun 25, 5:08=A0pm, Myth__Buster <raghavani...@gmail.com> wrote:
>=20
> > Assume that the above code runs on a machine wherein the data pointers =
and function pointers are of different sizes. Then, what malloc returns is =
a function pointer but after casting it to void* while returning(Or, after =
assigning it to a void* variable internally and returning its value).
> >
> > Now, isn't malloc giving us the truncated address in the above context?=
 Consider the same question applicable to calloc and realloc when used in s=
uch a context.
>=20
> malloc always returns a data pointer. You can ask it to return a data
> pointer to some memory area that is big enough to hold a function
> pointer, but it will still be a data pointer.
>=20
> Maybe the situation would be less confusing to you if you first
> declare a struct with a single member that is a function pointer, then
> use malloc to return a data pointer pointing to one such struct.

Yeah, had thought of it earlier(struct-approach being feasible due to data =
pointer involvement). But, wanted to accomplish the same with a malloc call=
 by passing the sizeof a function pointer. So, malloc's documentation shoul=
d include a note on this, isn't it?
0
Reply raghavanil4m (37) 6/25/2012 7:08:04 PM

On 06/25/2012 03:08 PM, Myth__Buster wrote:
> On Monday, June 25, 2012 9:16:07 AM UTC-7, christian.bau wrote:
>> On Jun 25, 5:08 pm, Myth__Buster <raghavani...@gmail.com> wrote:
>>
>>> Assume that the above code runs on a machine wherein the data pointers and function pointers are of different sizes. Then, what malloc returns is a function pointer but after casting it to void* while returning(Or, after assigning it to a void* variable internally and returning its value).
>>>
>>> Now, isn't malloc giving us the truncated address in the above context? Consider the same question applicable to calloc and realloc when used in such a context.
>>
>> malloc always returns a data pointer. You can ask it to return a data
>> pointer to some memory area that is big enough to hold a function
>> pointer, but it will still be a data pointer.
>>
>> Maybe the situation would be less confusing to you if you first
>> declare a struct with a single member that is a function pointer, then
>> use malloc to return a data pointer pointing to one such struct.
> 
> Yeah, had thought of it earlier(struct-approach being feasible due to data pointer involvement). But, wanted to accomplish the same with a malloc call by passing the sizeof a function pointer. So, malloc's documentation should include a note on this, isn't it?

I think you've got some confusion about something, possibly about levels
of indirection. Could you give an example of what you wanted to do with
such a pointer? I noticed that your original message contained a
definition for a function named f, which was not used in any way within
your code - I suspect that has something to do with your question, but
I'm not sure what.
0
Reply jameskuyper (5170) 6/25/2012 7:27:44 PM

On Monday, June 25, 2012 9:52:22 AM UTC-7, James Kuyper wrote:
> On 06/25/2012 12:08 PM, Myth__Buster wrote:
> > In reference with the below code,
> >=20
> > #include <stdlib.h>
> > #include <stdio.h>
> >=20
> > int f(void)
> > {
> > printf("\n In f . . . \n");
> > }
> >=20
> > int main(void)
> > {
> > int (*p)(void) =3D malloc(sizeof(int (*)(void)));
>=20
> "The pointer returned if the allocation succeeds is suitably aligned so
> that it may be assigned to a pointer to any type of object ..."
> (7.22.3p1). Note carefully that this only applies to pointers to object
> types, not function types.
>=20
> The code above converts a pointer to void into a pointer to a function
> type. The behavior of this code is well-defined if malloc() fails,
> because 6.3.6.2p4 says "Conversion of a null pointer to another pointer
> type yields a null pointer of that type." However, the behavior of this
> code is undefined if malloc() returns a non-null pointer "by omission of
> any explicit definition of the behavior" (4p2). The only other
> conversion defined by the standard that involves function pointer types
> is the conversion from one function pointer type to another (6.3.6.3p8),
> which doesn't apply here.
>=20
> > return 0;
> > }
> >=20
> > I would like to question about the return type of malloc(calloc, and
> > realloc).
>=20
> All three functions behave the same, as far as the issue raided by your
> message is concerned.
>=20
> > Assume that the above code runs on a machine wherein the data
> > pointers and function pointers are of different sizes. Then, what
> > malloc returns is a function pointer ...
>=20
> That's incorrect - what gave you that idea? The rest of your message
> depends upon that misconception, so I'll just stop here.

Well, am aware of the possible implications of converting a void* into a fu=
nction pointer. But, the initialization of function pointer p is present on=
ly for the completeness of the code. For the question being discussed, let'=
s consider the code as under :

#include <stdlib.h>
int main(void)
{
    (void)malloc(sizeof(int (*)(void))); // Ignore the usability of this st=
atement, possible          =20
                                  // memory-leaks, and any other trivial fa=
ctors involved=20
                                  // which are irrelevant to the question b=
eing discussed.
     return 0;
}

Now, would like to reiterate myself - malloc() returns a void*(data pointer=
 as always known) even when we have allocated memory for a function pointer=
 on a machine wherein data and function pointers are of different sizes. Th=
is behavior of malloc appears to me as improper and hence I am questioning =
its generality of returning a void*(data pointer) always. Shouldn't there b=
e a note in malloc's documentation regarding such usage?

Cheers,
Raghavan Santhanam
0
Reply raghavanil4m (37) 6/25/2012 7:28:40 PM

On 6/25/2012 3:08 PM, Myth__Buster wrote:
> On Monday, June 25, 2012 9:16:07 AM UTC-7, christian.bau wrote:
>> On Jun 25, 5:08 pm, Myth__Buster <raghavani...@gmail.com> wrote:
>>
>>> Assume that the above code runs on a machine wherein the data pointers and function pointers are of different sizes. Then, what malloc returns is a function pointer but after casting it to void* while returning(Or, after assigning it to a void* variable internally and returning its value).
>>>
>>> Now, isn't malloc giving us the truncated address in the above context? Consider the same question applicable to calloc and realloc when used in such a context.
>>
>> malloc always returns a data pointer. You can ask it to return a data
>> pointer to some memory area that is big enough to hold a function
>> pointer, but it will still be a data pointer.
>>
>> Maybe the situation would be less confusing to you if you first
>> declare a struct with a single member that is a function pointer, then
>> use malloc to return a data pointer pointing to one such struct.
>
> Yeah, had thought of it earlier(struct-approach being feasible due to data pointer involvement). But, wanted to accomplish the same with a malloc call by passing the sizeof a function pointer. So, malloc's documentation should include a note on this, isn't it?

     Wouldn't that be sort of like "Warning: May Contain Nuts" on
a bag of peanuts?

     Aiming a function pointer at allocated memory (at any data object,
for that matter) is non-portable, as you've observed.  But filling the
allocated memory with something that can be called like a function is
also non-portable.  Seems to me that anyone playing such games already
needs a good deal of non-portable knowledge about the implementation:
He's purchased his packet of peanuts, on purpose.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid


0
Reply esosman2 (2945) 6/25/2012 7:30:12 PM

Myth__Buster <raghavanil4m@gmail.com> writes:

> On Monday, June 25, 2012 9:16:07 AM UTC-7, christian.bau wrote:
>> On Jun 25, 5:08 pm, Myth__Buster <raghavani...@gmail.com> wrote:
>> 
>> > Assume that the above code runs on a machine wherein the data
>> > pointers and function pointers are of different sizes. Then, what
>> > malloc returns is a function pointer but after casting it to void*
>> > while returning(Or, after assigning it to a void* variable
>> > internally and returning its value).
>> >
>> > Now, isn't malloc giving us the truncated address in the above
>> > context? Consider the same question applicable to calloc and
>> > realloc when used in such a context.
>> 
>> malloc always returns a data pointer. You can ask it to return a data
>> pointer to some memory area that is big enough to hold a function
>> pointer, but it will still be a data pointer.
>> 
>> Maybe the situation would be less confusing to you if you first
>> declare a struct with a single member that is a function pointer, then
>> use malloc to return a data pointer pointing to one such struct.
>
> Yeah, had thought of it earlier(struct-approach being feasible due to
> data pointer involvement). But, wanted to accomplish the same with a
> malloc call by passing the sizeof a function pointer. So, malloc's
> documentation should include a note on this, isn't it?

No, there is no problem with what you say you want to do, just how you
are doing it.

  malloc(sizeof (int (*)(void)))

is fine.  It allocates enough room for a pointer to a function, but what
it returned is a pointer to that space.  I.e. the correct way to store
the result is either as a void * (which is not often that useful) or as
a pointer to a pointer to a function:

  int (**p)(void) = malloc(sizeof (int (*)(void)));

It's an mistake to try to convert what comes back from malloc into a
pointer to a function.  Even if you could so this safely (and you might
on some forgiving systems) the space you allocate should be for a
function, not a pointer to one.

So, if you want to allocate space for a pointer to a function, go right
ahead, as above.  If you want to allocate space for a function (and thus
get a pointer to one from malloc) you are out of luck in standard C.  It
might be possible to get round some of the problems on some systems, but
that's another matter.

Note that the comp.lang.c approved what to write malloc calls helps here
(like it helps inmost cases).  The patter being:

  T *p = malloc(sizeof *p);

You can write the allocation like this:

  int (**p)(void) = malloc(sizeof *p);

Had you tried to other possibility:

  int (*p)(void) = malloc(sizeof *p);

you should expect an error message -- something along the lines of:

  warning: invalid application of 'sizeof' to a function type

So, after all that, what do you want -- to allocate space for a function
pointer, or to allocate space for a function?

-- 
Ben.
0
Reply ben.usenet (6515) 6/25/2012 7:42:45 PM

On Monday, June 25, 2012 12:30:12 PM UTC-7, Eric Sosman wrote:
> On 6/25/2012 3:08 PM, Myth__Buster wrote:
> > On Monday, June 25, 2012 9:16:07 AM UTC-7, christian.bau wrote:
> >> On Jun 25, 5:08 pm, Myth__Buster <raghavani...@gmail.com> wrote:
> >>
> >>> Assume that the above code runs on a machine wherein the data pointer=
s and function pointers are of different sizes. Then, what malloc returns i=
s a function pointer but after casting it to void* while returning(Or, afte=
r assigning it to a void* variable internally and returning its value).
> >>>
> >>> Now, isn't malloc giving us the truncated address in the above contex=
t? Consider the same question applicable to calloc and realloc when used in=
 such a context.
> >>
> >> malloc always returns a data pointer. You can ask it to return a data
> >> pointer to some memory area that is big enough to hold a function
> >> pointer, but it will still be a data pointer.
> >>
> >> Maybe the situation would be less confusing to you if you first
> >> declare a struct with a single member that is a function pointer, then
> >> use malloc to return a data pointer pointing to one such struct.
> >
> > Yeah, had thought of it earlier(struct-approach being feasible due to d=
ata pointer involvement). But, wanted to accomplish the same with a malloc =
call by passing the sizeof a function pointer. So, malloc's documentation s=
hould include a note on this, isn't it?
>=20
>      Wouldn't that be sort of like "Warning: May Contain Nuts" on
> a bag of peanuts?
>=20
>      Aiming a function pointer at allocated memory (at any data object,
> for that matter) is non-portable, as you've observed.  But filling the
> allocated memory with something that can be called like a function is
> also non-portable.  Seems to me that anyone playing such games already
> needs a good deal of non-portable knowledge about the implementation:
> He's purchased his packet of peanuts, on purpose.
>=20
> --=20
> Eric Sosman
> esosman@ieee-dot-org.invalid

The programmer might be well aware of this inability of malloc in returning=
 a function pointer. However, shouldn't there be a relevant note under mall=
oc's documentation for the sake of clarity and completeness of malloc's beh=
avior?

Cheers,
Raghavan Santhanam
0
Reply raghavanil4m (37) 6/25/2012 7:47:14 PM

On 06/25/2012 03:28 PM, Myth__Buster wrote:
....
> Well, am aware of the possible implications of converting a void* into a function pointer. But, the initialization of function pointer p is present only for the completeness of the code. For the question being discussed, let's consider the code as under :
> 
> #include <stdlib.h>
> int main(void)
> {
>     (void)malloc(sizeof(int (*)(void))); // Ignore the usability of this statement, possible           
>                                   // memory-leaks, and any other trivial factors involved 
>                                   // which are irrelevant to the question being discussed.
>      return 0;
> }
> 
> Now, would like to reiterate myself - malloc() returns a void*(data pointer as always known) even when we have allocated memory for a function pointer on a machine wherein data and function pointers are of different sizes. This behavior of malloc appears to me as improper and hence I am questioning its generality of returning a void*(data pointer) always. Shouldn't there be a note in malloc's documentation regarding such usage?

That depends upon what the problem is that you're talking about, which I
do not yet understand. If it is a problem with the specification of
malloc() provided by the C standard, then by definition the
documentation of malloc() already mentions it, if only implicitly. If
it's a problem with a particular implementation of malloc(), I agree
with you that the implementation's documentation for malloc() should be
modified to mention it.

Could you provide an example of code that would cause problems due to
the impropriety you perceive? The above code has no problems worse than
a memory leak. malloc() allocates enough space to store a pointer to a
function type, even if that space is larger than would be needed to
store a pointer to an object type. The function pointer itself has an
object type, and malloc() returns a void* pointer that can be converted
to pointer to a function pointer of that type, which is itself a data
pointer, and therefore, on such an implementation, has a different size.

Let me provide my own example, based upon yours, which may clarify the
issue for you:

#include <stdlib.h>
int f(void) {
    printf("f() will return 1.\n");
    return 1;
}

int main(void)
{
    int (**p)(void) = malloc(sizeof *p);
    if(p)
    {
	printf("p() returned %d\n", (*p)());
	free(p);
    }
    return 0;
}

Now, *p has a pointer-to-function type: int (*)(void). p itself has a
pointer-to-data type: int (**)(void). On a machine such as you describe,
sizeof p would be different from sizeof *p. If all pointers on that
machine have only one of those two sizes, then sizeof(void*), the size
of the pointer that is returned by malloc(), will certainly be the same
as sizeof p, not sizeof *p. I get the impression that you consider this
problematic. Could you provide an explanation or at least an example of
how you think this could be problematic?

Note: under modern C rules, (*p)() could also have been written as
simply p(), without change in meaning. This is a syntactic convenience,
but potentially confusing. In this context I thought I should avoid any
unnecessary potential confusion.
0
Reply jameskuyper (5170) 6/25/2012 7:59:30 PM

On 6/25/2012 3:47 PM, Myth__Buster wrote:
> On Monday, June 25, 2012 12:30:12 PM UTC-7, Eric Sosman wrote:
>> On 6/25/2012 3:08 PM, Myth__Buster wrote:
>>>[...]
>>> Yeah, had thought of it earlier(struct-approach being feasible due to data pointer involvement). But, wanted to accomplish the same with a malloc call by passing the sizeof a function pointer. So, malloc's documentation should include a note on this, isn't it?
>>
>>       Wouldn't that be sort of like "Warning: May Contain Nuts" on
>> a bag of peanuts?
>>
>>       Aiming a function pointer at allocated memory (at any data object,
>> for that matter) is non-portable, as you've observed.  But filling the
>> allocated memory with something that can be called like a function is
>> also non-portable.  Seems to me that anyone playing such games already
>> needs a good deal of non-portable knowledge about the implementation:
>> He's purchased his packet of peanuts, on purpose.
>
> The programmer might be well aware of this inability of malloc in returning a function pointer. However, shouldn't there be a relevant note under malloc's documentation for the sake of clarity and completeness of malloc's behavior?

     If the programmer is "well aware" that function pointers and data
pointers are incommensurate, what purpose would the note serve?  How
would you word such a note?  "NOTE: You already know this?"

     Programs exist (I have maintained -- and debugged! -- a few)
that allocate memory, fill it with magic values, aim a function
pointer at it, and perform a call through the pointer.  I suggest
that anyone writing such code is already keenly aware that it is
non-portable, also keenly aware of specific characteristics of his
C implementation that are not part of the C language.  He already
knows whether his system's function pointers are bare addresses or
more structured "function descriptors," he knows about special
prologue and epilogue sequences that wrap the instructions, he
knows about cache-coherency incantations that must be performed
between filling the memory and calling its content, and so on, and
so on.

     But perhaps I'm missing something, some other purpose for aiming
a function pointer at data.  What do you intend to *do* with the data?

-- 
Eric Sosman
esosman@ieee-dot-org.invalid


0
Reply esosman2 (2945) 6/25/2012 8:10:51 PM

Myth__Buster <raghavanil4m@gmail.com> writes:
> In reference with the below code,
>
> #include <stdlib.h>
> #include <stdio.h>
>
> int f(void)
> {
>     printf("\n In f . . . \n");
> }
>
> int main(void)
> {
>     int (*p)(void) = malloc(sizeof(int (*)(void)));
>     
>     return 0;     
> }

The above code is invalid; it contains a constraint violation, and any
conforming compiler must at least emit a diagnostic for it.

malloc() returns a result of type void*.  You're attempting to use that
result to initialize an object of type int(*)(void), i.e., a
pointer-to-function type.

Initialization imposes the same type requirements as simple assignment.

Section 6.5.16.1 of N1570 lists the valid combinations of types for a
simple assignment; the list does not include this case.

There's an implicit conversion from void* to any pointer-to-object
type.  There is no such implicit conversion from void* to any
pointer-to-function type.

> I would like to question about the return type of malloc(calloc, and
> realloc).
>
> Assume that the above code runs on a machine wherein the data pointers
> and function pointers are of different sizes. Then, what malloc
> returns is a function pointer but after casting it to void* while
> returning(Or, after assigning it to a void* variable internally and
> returning its value).
>
> Now, isn't malloc giving us the truncated address in the above
> context? Consider the same question applicable to calloc and realloc
> when used in such a context.

If you make the conversion explicit, using a cast, then I believe there
is no constraint violation:

    int (*p)(void) = malloc(sizeof(int (*)(void)));

However the standard says nothing about the behavior of a conversion
from void* to a pointer-to-function type, so the behavior is undefined
by omission.  The standard says nothing about "truncating" pointer
values; it simply doesn't define the result or behavior of the
conversion.

The authors of gcc apparently interpret the standard differently; with
"-std=c99 -pedantic", gcc 5.7 warns:

    warning: ISO C forbids conversion of object pointer to function pointer type [-pedantic]

I'll post to comp.std.c and see if I can get this clarified.

What is your code intended to do?  If you're trying to allocate space
for a single function pointer, then you need a
pointer-to-pointer-to-function to point to it.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21480) 6/25/2012 8:13:48 PM

On Monday, June 25, 2012 12:42:45 PM UTC-7, Ben Bacarisse wrote:
> Myth__Buster <raghavanil4m@gmail.com> writes:
>=20
> > On Monday, June 25, 2012 9:16:07 AM UTC-7, christian.bau wrote:
> >> On Jun 25, 5:08=A0pm, Myth__Buster <raghavani...@gmail.com> wrote:
> >>=20
> >> > Assume that the above code runs on a machine wherein the data
> >> > pointers and function pointers are of different sizes. Then, what
> >> > malloc returns is a function pointer but after casting it to void*
> >> > while returning(Or, after assigning it to a void* variable
> >> > internally and returning its value).
> >> >
> >> > Now, isn't malloc giving us the truncated address in the above
> >> > context? Consider the same question applicable to calloc and
> >> > realloc when used in such a context.
> >>=20
> >> malloc always returns a data pointer. You can ask it to return a data
> >> pointer to some memory area that is big enough to hold a function
> >> pointer, but it will still be a data pointer.
> >>=20
> >> Maybe the situation would be less confusing to you if you first
> >> declare a struct with a single member that is a function pointer, then
> >> use malloc to return a data pointer pointing to one such struct.
> >
> > Yeah, had thought of it earlier(struct-approach being feasible due to
> > data pointer involvement). But, wanted to accomplish the same with a
> > malloc call by passing the sizeof a function pointer. So, malloc's
> > documentation should include a note on this, isn't it?
>=20
> No, there is no problem with what you say you want to do, just how you
> are doing it.
>=20
>   malloc(sizeof (int (*)(void)))
>=20
> is fine.  It allocates enough room for a pointer to a function, but what
> it returned is a pointer to that space.  I.e. the correct way to store
> the result is either as a void * (which is not often that useful) or as
> a pointer to a pointer to a function:
>=20
>   int (**p)(void) =3D malloc(sizeof (int (*)(void)));
>=20
> It's an mistake to try to convert what comes back from malloc into a
> pointer to a function.  Even if you could so this safely (and you might
> on some forgiving systems) the space you allocate should be for a
> function, not a pointer to one.
>=20
> So, if you want to allocate space for a pointer to a function, go right
> ahead, as above.  If you want to allocate space for a function (and thus
> get a pointer to one from malloc) you are out of luck in standard C.  It
> might be possible to get round some of the problems on some systems, but
> that's another matter.
>=20
> Note that the comp.lang.c approved what to write malloc calls helps here
> (like it helps inmost cases).  The patter being:
>=20
>   T *p =3D malloc(sizeof *p);
>=20
> You can write the allocation like this:
>=20
>   int (**p)(void) =3D malloc(sizeof *p);
>=20
> Had you tried to other possibility:
>=20
>   int (*p)(void) =3D malloc(sizeof *p);
>=20
> you should expect an error message -- something along the lines of:
>=20
>   warning: invalid application of 'sizeof' to a function type
>=20
> So, after all that, what do you want -- to allocate space for a function
> pointer, or to allocate space for a function?
>=20
> --=20
> Ben.

Well,=20

Yeah, I know, that's the usual pattern - when we allocate a certain chunk o=
f memory for an object of type T, we would be storing the respective malloc=
's return value in an object of type T*. No questions on that beginner's as=
pect.=20

In my question being discussed, we are allocating space for a function poin=
ter which might *not* be of same size as that of a data pointer on some mac=
hines. No questions on the allocation. It's fine and clear to me. But, the =
data pointer(void*) being returned by malloc will be improper to access the=
 allocated space for the function pointer. And hence, I would like to see a=
 relevant note under malloc's documentation.

Of course, I would like to allocate space for a function pointer using mall=
oc without any dependency on any third-variable such as struct variable, et=
c, and use it thereafter(regarding the usage, that will be another story. I=
 am interested in getting a proper pointer in the first place from malloc).=
 And yeah, in the realms of C, allocating space for a function is meaningle=
ss as we know sizeof a function makes no sense. :)

Cheers,
Raghavan Santhanam
0
Reply raghavanil4m (37) 6/25/2012 8:14:16 PM

On Jun 25, 5:08=A0pm, Myth__Buster <raghavani...@gmail.com> wrote:
> In reference with the below code,
>
> #include <stdlib.h>
> #include <stdio.h>
>
> int f(void)
> {
> =A0 =A0 printf("\n In f . . . \n");
>
> }
>
> int main(void)
> {
> =A0 =A0 int (*p)(void) =3D malloc(sizeof(int (*)(void)));
>
> =A0 =A0 return 0;
>
> }
>
> I would like to question about the return type of malloc(calloc, and real=
loc).
>
> Assume that the above code runs on a machine wherein the data pointers an=
d function pointers are of different sizes. Then, what malloc returns is a =
function pointer but after casting it to void* while returning(Or, after as=
signing it to a void* variable internally and returning its value).
>
> Now, isn't malloc giving us the truncated address in the above context? C=
onsider the same question applicable to calloc and realloc when used in suc=
h a context.

I'm not sure what you're trying to do. Is your idea to make a copy of
f and then stomp all over the code of the copy so that it does
something different from f itself? Or are you simply wanting to call
already-existing functions?

If you are really trying to re-write a function, then you will need to
know a lot about how your particular system works. For instance, you
will need to know how big the function is, which I don't think
standard C can tell you.

If, instead, you simply have several functions and you want to use a
function pointer to call them, then it's probably easiest just to use
a variable of type pointer-to-function and not mess about with malloc
at all.

Hope that helps.
Paul.
0
Reply gw7rib (462) 6/25/2012 8:17:46 PM

On 06/26/12 08:14 AM, Myth__Buster wrote:

Please wrap your lines!

> Well,
>
> Yeah, I know, that's the usual pattern - when we allocate a certain chunk of memory for an object of type T, we would be storing the respective malloc's return value in an object of type T*. No questions on that beginner's aspect.
>
> In my question being discussed, we are allocating space for a function pointer which might *not* be of same size as that of a data pointer on some machines. No questions on the allocation. It's fine and clear to me. But, the data pointer(void*) being returned by malloc will be improper to access the allocated space for the function pointer. And hence, I would like to see a relevant note under malloc's documentation.

What would that achieve?  malloc returns a void* and a void* is not 
compatible with a function pointer.  Would you add a note for every 
function that returns something incompatible with something else?

-- 
Ian Collins
0
Reply ian-news (9882) 6/25/2012 8:30:14 PM

On 06/25/2012 04:14 PM, Myth__Buster wrote:
....
> In my question being discussed, we are allocating space for a
> function pointer which might *not* be of same size as that of a data
> pointer on some machines. No questions on the allocation. It's fine
> and clear to me. But, the data pointer(void*) being returned by
> malloc will be improper to access the allocated space for the
> function pointer. ...

The function pointer itself has an object type, and you've instructed
malloc() to allocate enough memory to hold it for you. The data pointer
returned by malloc() will be perfectly usable for accessing the memory
you've allocated for the function pointer. Why do you think otherwise?

....
> ... regarding the usage, that
> will be another story. I am interested in getting a proper pointer in
> the first place from malloc ...

Don't worry about getting a proper pointer in the first place from
malloc() - if what you're trying to do makes any sense, and if it makes
sense to use malloc() as part of the solution to your problem, then I
guarantee you that the pointer returned by malloc() will be proper.
Telling us what you want to do with this pointer after you've allocated
might help us figure out why you think otherwise.

0
Reply jameskuyper (5170) 6/25/2012 8:47:03 PM

>=20
> What would that achieve?  malloc returns a void* and a void* is not=20
> compatible with a function pointer.  Would you add a note for every=20
> function that returns something incompatible with something else?
>=20
> --=20
> Ian Collins

Achievement : Clarity and completeness of malloc's behavior in malloc's doc=
umentation. More appropriately, a word of caution similar to this - In C, m=
alloc when used to directly allocate memory for function pointers(without a=
ny third-variable's allocation such as encompassing struct variable, etc) o=
n machines wherein the data and function pointers are of different sizes, t=
he return data pointer wouldn't be a proper pointer with which the entire m=
emory allocated for function pointer would have been allocated. Hence, care=
 should be exercised before the allocated memory could be used. (On similar=
 lines, the applicable alternative approaches can be mentioned therein to a=
ccomplish the same and thereby help the reader/programmer).

Cheers,
Raghavan Santhanam
0
Reply raghavanil4m (37) 6/25/2012 8:53:10 PM

*Completed my sentences.

On Monday, June 25, 2012 1:53:10 PM UTC-7, Myth__Buster wrote:
> >=20
> > What would that achieve?  malloc returns a void* and a void* is not=20
> > compatible with a function pointer.  Would you add a note for every=20
> > function that returns something incompatible with something else?
> >=20
> > --=20
> > Ian Collins
>=20
> Achievement : Clarity and completeness of malloc's behavior in malloc's d=
ocumentation. More appropriately, a word of caution similar to this - In C,=
 malloc when used to directly allocate memory for function pointers(without=
 any third-variable's allocation such as encompassing struct variable, etc)=
 on machines wherein the data and function pointers are of different sizes,=
 the return data pointer wouldn't be a proper pointer with which the entire=
 memory allocated for function pointer could be accessed. Hence, care shoul=
d be exercised before the allocated memory could be used. (On similar lines=
, the applicable alternative approaches can be mentioned therein to accompl=
ish the same and thereby help the reader/programmer).
>=20
> Cheers,
> Raghavan Santhanam

0
Reply raghavanil4m (37) 6/25/2012 8:58:17 PM

On 06/26/12 08:53 AM, Myth__Buster wrote:
>>
>> What would that achieve?  malloc returns a void* and a void* is not
>> compatible with a function pointer.  Would you add a note for every
>> function that returns something incompatible with something else?
>>
>> --
>> Ian Collins
>
> Achievement : Clarity and completeness of malloc's behavior in malloc's documentation.

Should it also caution that the return type of malloc is incompatible 
with int?  with char?  with ...

-- 
Ian Collins
0
Reply ian-news (9882) 6/25/2012 9:00:38 PM

> In my question being discussed, we are allocating space for a
>function pointer which might *not* be of same size as that of a
>data pointer on some machines. 

Note that I can allocate space for a long double, a char, or a
really big struct, or an array of many pointers, which also might
not be of the same size as that of a data pointer on some machines.
This is irrelevant.  malloc() returns a data pointer which is fine
for this.

>No questions on the allocation. It's
>fine and clear to me. 

>But, the data pointer(void*) being returned
>by malloc will be improper to access the allocated space for the
>function pointer. 

Incorrect.  It is improper to access a function pointer by indirecting
through a function pointer.  It is proper to access a function pointer
by indirecting through a data (object) pointer.

The allocated space contains a function pointer (not a function),
and a pointer to a function pointer is a *data* pointer to a function
pointer.

It is improper to access anything but functions (not function
pointers, just functions) with a function pointer.  You do this
by calling the function.

>And hence, I would like to see a relevant note
>under malloc's documentation.

If you could write code like this:

int main(int argc, char **argv)
{
	void *mainptr = malloc(sizeof(main));	/* allocate space */
	memcpy(mainptr, &main, sizeof(main));  /* make a copy of main() */
	return (*mainptr)(argc, argv);	/* call the copy */
}

it might make some sense, but you can't.  sizeof() doesn't work on
functions (function pointers, yes, not on functions).  memcpy()
doesn't accept function pointers.  A copy of a function is not
guaranteed to execute at all, or execute properly.  Plus, this example
generates infinite recursion.


0
Reply gordonb.vk4xa (1) 6/25/2012 9:06:16 PM

Myth__Buster <raghavanil4m@gmail.com> writes:
[...]
> Well, am aware of the possible implications of converting a void* into
> a function pointer. But, the initialization of function pointer p is
> present only for the completeness of the code. For the question being
> discussed, let's consider the code as under :
>
> #include <stdlib.h>
> int main(void)
> {
>     (void)malloc(sizeof(int (*)(void)));
>         // Ignore the usability of this statement, possible
>         // memory-leaks, and any other trivial factors involved
>         // which are irrelevant to the question being discussed.
>      return 0;
> }
>
> Now, would like to reiterate myself - malloc() returns a void*(data
> pointer as always known) even when we have allocated memory for a
> function pointer on a machine wherein data and function pointers are
> of different sizes. This behavior of malloc appears to me as improper
> and hence I am questioning its generality of returning a void*(data
> pointer) always. Shouldn't there be a note in malloc's documentation
> regarding such usage?

The expression

    sizeof(int (*)(void))

yields a value of type size_t.  The particular value is likely to be 4
or 8 on many typical systems.

malloc() only sees this value as its parameter; it doesn't know or care
that it happens to be the size of a function pointer.  So you might as
well have written:
    (void)malloc(4);
or
    (void)malloc(8);

malloc will attempt to allocate that many bytes of memory, and will
return a void* value that points to it (or a null pointer if the
allocation fails).

If you like, you can then use that allocated memory as an object of
pointer-to-function type.  There's nothing problematic about that.  A
function pointer is just another data type, like an object pointer, an
integer, a floating-point object, or a struct object.

But if you want to use malloc() to allocate an object of some type, you
need to convert the result to a pointer to that type.  Your original
code didn't do that correctly; it attempted to convert the result of
malloc() to a pointer-to-function type rather than to a
pointer-to-pointer-to-function type.

A typedef might make this a bit clearer:

    typedef void (*func_ptr)(void);
    ...
    func_ptr *p = malloc(sizeof *p);

p is a pointer to a pointer to function.

Another thing that you might *think* you can do is to set a function
pointer to point to space allocated by malloc():

    func_ptr wrong = malloc(some_size);

For this to work, some_size would probably have to indicate the size of
the function.  (That's assuming function pointers are implemented as
pointers to the function's code, which is not specified; a function
pointer might instead point to some kind of descriptor, for
example). You'd also need some way to initialize the newly allocated
memory so it acts like a function. This can be done on some systems, but
it's *extremely* system-specific.

What I *think* you're trying to do is allocate a single
pointer-to-function object using malloc() (that's the closest thing to
the code you showed us that makes any sense).  But it's not clear *why*
you're doing this. If you're only allocating space for a single pointer
object, why not just declare the object directly?

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21480) 6/25/2012 9:08:11 PM

On 06/25/2012 04:53 PM, Myth__Buster wrote:
....
> Achievement : Clarity and completeness of malloc's behavior in
> malloc's documentation. More appropriately, a word of caution similar
> to this - In C, malloc when used to directly allocate memory for
> function pointers(without any third-variable's allocation such as
> encompassing struct variable, etc) on machines wherein the data and
> function pointers are of different sizes, the return data pointer
> wouldn't be a proper pointer with which the entire memory allocated
> for function pointer would have been allocated.

I still don't understand why you think there's a problem, which
inherently implies that I don't understand what the problem is that you
think there is. However, that is not an accurate description of any
problem that malloc() actually possesses.
0
Reply jameskuyper (5170) 6/25/2012 9:13:55 PM

Myth__Buster <raghavanil4m@gmail.com> writes:
[...]
> Yeah, I know, that's the usual pattern - when we allocate a certain
> chunk of memory for an object of type T, we would be storing the
> respective malloc's return value in an object of type T*. No questions
> on that beginner's aspect.
>
> In my question being discussed, we are allocating space for a function
> pointer which might *not* be of same size as that of a data pointer on
> some machines. No questions on the allocation. It's fine and clear to
> me. But, the data pointer(void*) being returned by malloc will be
> improper to access the allocated space for the function pointer. And
> hence, I would like to see a relevant note under malloc's
> documentation.
>
> Of course, I would like to allocate space for a function pointer using
> malloc without any dependency on any third-variable such as struct
> variable, etc, and use it thereafter(regarding the usage, that will be
> another story. I am interested in getting a proper pointer in the
> first place from malloc). And yeah, in the realms of C, allocating
> space for a function is meaningless as we know sizeof a function makes
> no sense. :)

It *doesn't matter* whether the object being allocated happens to
have the same size as a void*.

Suppose you're allocating a struct object rather than a
pointer-to-function object. Suppose void* is 4 bytes, and your
structure is 1024 bytes. The issues are exactly the same as in the
case you're looking at.

For struct allocation, you need to convert (probably implicitly)
the void* value returned by malloc() to a pointer to the struct.

For pointer-to-function allocation, you need to convert (probably
implicitly) the void* value returned by malloc() to a pointer to
the pointer-to-function.

Pay careful attention to the parallel construction of the two preceding
paragraphs.

I think the fact that the object you're allocating is a pointer is
causing you to confuse the pointer object being allocated with a
pointer *to* that pointer object.  They're at two different levels
of indirection, and their relative sizes are not relevant.

You're imagining a special case where there really isn't one.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21480) 6/25/2012 9:17:21 PM

On 6/25/2012 4:14 PM, Myth__Buster wrote:
> [...]
> In my question being discussed, we are allocating space for a function pointer which might *not* be of same size as that of a data pointer on some machines. No questions on the allocation. It's fine and clear to me. But, the data pointer(void*) being returned by malloc will be improper to access the allocated space for the function pointer. And hence, I would like to see a relevant note under malloc's documentation.

     Thanks to Ben Bacarisse, I think I see what you're confused
about.  (It wasn't evident from the original erroneous code: Half
the respondents fixed the error by imagining a change to one side
of the assignment, and half chose to change the other.  That's a
fundamental problem with invalid code: There may be many different
correct codes at small "edit distances" from the original, with
each edit corresponding to a different idea of "the error.")

     Anyhow: A function pointer is a data type and has a sizeof, and
malloc() is perfectly capable of allocating space to hold objects
of that type.  The `void*' returned by malloc() is entirely proper
for accessing the allocated space; you can store function pointer
values in that space and retrieve them from it, and (if they're
valid values) you can make calls through them to actual functions.
A note saying "malloc() cannot allocate space for function pointers"
would not be a clarification, it would be incorrect.

     What malloc() cannot return is a pointer to memory capable of
holding a function.  Put another way, malloc() cannot return a
pointer to an actual, callable function, nor to memory that might
possibly hold such a thing.  (As far as C is concerned, functions
don't inhabit "memory" at all.)

     You seem hung up on the (possible) difference between the
sizeof a function pointer and sizeof(void*), but there's no reason
to be alarmed.  I'm sure you use malloc(sizeof(struct foo)) without
trouble, even when sizeof(struct foo) != sizeof(void*).  The size
of a pointed-at thing and the size of the pointer to it need not
be related at all -- and that's the case when the pointed-at thing
is a function pointer, too.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid


0
Reply esosman2 (2945) 6/25/2012 9:24:57 PM

On 2012-06-25 20:58:17 +0000, Myth__Buster said:
> 
> On Monday, June 25, 2012 1:53:10 PM UTC-7, Myth__Buster wrote:
>> 
>> What would that achieve?  malloc returns a void* and a void* is not> > 
>> compatible with a function pointer.  Would you add a note for every> > 
>> function that returns something incompatible with something else?
>> 
>> -- 
>> Ian Collins
> 
> Achievement : Clarity and completeness of malloc's behavior in malloc's 
> documentation. More appropriately, a word of caution similar to this - 
> In C, malloc when used to directly allocate memory for function 
> pointers(without any third-variable's allocation such as encompassing 
> struct variable, etc) on machines wherein the data and function 
> pointers are of different sizes, the return data pointer wouldn't be a 
> proper pointer with which the entire memory allocated for function 
> pointer could be accessed. Hence, care should be exercised before the 
> allocated memory could be used. (On similar lines, the applicable 
> alternative approaches can be mentioned therein to accomplish the same 
> and thereby help the reader/programmer).

Given the declaration
    int (*p)(void) = malloc(sizeof(int (*)(void)));
and reading it "for intent" rather than as written:
 - 'p' identifies a function pointer value.
 - malloc is being (mis-)used to allocate memory for a function, and is 
incorrectly being expected to return a pointer to that function.

The second thing is flatly nonsensical. Nothing malloc could reasonably 
do with the block of memory it allocates could make that block into a 
function, and C does not provide tools for composing functions in 
random blocks of memory, so there's no way subsequent code could turn 
the block into a legitimate function either.

I don't know how you've gotten to "malloc is allocating a function 
pointer" here. It's not: it's allocating a block of memory, then 
*returning* a (value) pointer to that block. Trying to interpret the 
pointed-to block as a function will at best crash your program, so the 
returned pointer cannot be interpreted as a pointer to a function. 
(Ignoring the case where malloc returns a null pointer.)

The only sensible values for function pointers (which 'p' already 
identifies, without any need for dynamic allocation of a pointer-sized 
block) are the values obtainable from the addresses of functions in 
your program:

	int random_number(void) {
		return 4; /* generated by fair die roll */
	}

	int main(void) {
		int (*p)(void) = random_number;
		/* and so on */
		return 0;
	}

It's completely unnecessary to note in the docs that malloc can't 
return a function pointer for the same reason that's unnecessary to 
mention that memcpy can't receive a function pointer as an argument: 
it's taken as given that if you use function pointers, you understand 
how they're different from value pointers, and how the pointed-to 
entities differ in both allocation and behaviour. Non-null function 
pointers are *never* compatible with value pointers, and vice versa, as 
far as I know.

If you really wanted to use malloc to "allocate a function pointer" 
(for whatever unlikely reason), you'd need to add another step of 
indirection, and declare 'p' as a pointer to a function pointer:

	int (**p)(void) = malloc(sizeof(*p));
	if (p != NULL) {
		*p = random_number;
		/* and so on */
	}

Here, malloc allocates a block at least the size of a function pointer, 
and returns a pointer *to* that block. I can't imagine why you'd write 
code this way, though.

-o

0
Reply angrybaldguy (338) 6/26/2012 4:03:39 AM

On Mon, 25 Jun 2012 12:28:40 -0700, Myth__Buster wrote:

> Now, would like to reiterate myself - malloc() returns a void*(data
> pointer as always known) even when we have allocated memory for a function
> pointer on a machine wherein data and function pointers are of different
> sizes. This behavior of malloc appears to me as improper

Why?

> and hence I am questioning its generality of returning a void*(data
> pointer) always.

All pointers are data, and all pointers to data are data pointers,
including pointers to function pointers.

If you malloc() space for a function pointer, malloc returns a pointer to
that space. Whether or not you actually use that space to hold a function
pointer is irrelevant.

0
Reply nobody (4805) 6/26/2012 8:29:44 PM

25 Replies
45 Views

(page loaded in 0.241 seconds)


Reply: