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

Discussion in 'C Programming' started by Myth__Buster, Jun 25, 2012.

  1. Myth__Buster

    Myth__Buster Guest

    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;

    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.

    Raghavan Santhanam
    Myth__Buster, Jun 25, 2012
    1. Advertisements

  2. Myth__Buster

    James Kuyper Guest

    "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 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 (,
    which doesn't apply here.
    All three functions behave the same, as far as the issue raided by your
    message is concerned.
    That's incorrect - what gave you that idea? The rest of your message
    depends upon that misconception, so I'll just stop here.
    James Kuyper, Jun 25, 2012
    1. Advertisements

  3. Myth__Buster

    Myth__Buster Guest

    Yeah, had thought of it earlier(struct-approach being feasible due to data pointer involvement). But, wanted to accomplish the same with a malloc callby passing the sizeof a function pointer. So, malloc's documentation should include a note on this, isn't it?
    Myth__Buster, Jun 25, 2012
  4. Myth__Buster

    James Kuyper Guest

    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.
    James Kuyper, Jun 25, 2012
  5. Myth__Buster

    Myth__Buster Guest

    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 pointeras always known) even when we have allocated memory for a function pointeron 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?

    Raghavan Santhanam
    Myth__Buster, Jun 25, 2012
  6. Myth__Buster

    Eric Sosman Guest

    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, Jun 25, 2012
  7. 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 Bacarisse, Jun 25, 2012
  8. Myth__Buster

    Myth__Buster Guest

    The programmer might be well aware of this inability of malloc in returninga 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?

    Raghavan Santhanam
    Myth__Buster, Jun 25, 2012
  9. Myth__Buster

    James Kuyper Guest

    On 06/25/2012 03:28 PM, Myth__Buster wrote:
    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);
    printf("p() returned %d\n", (*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.
    James Kuyper, Jun 25, 2012
  10. Myth__Buster

    Eric Sosman Guest

    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, Jun 25, 2012
  11. 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 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.
    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

    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, Jun 25, 2012
  12. Myth__Buster

    Myth__Buster Guest


    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 theallocated space for the function pointer. And hence, I would like to see arelevant 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. Iam 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. :)

    Raghavan Santhanam
    Myth__Buster, Jun 25, 2012
  13. Myth__Buster

    Paul N Guest

    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 N, Jun 25, 2012
  14. Myth__Buster

    Ian Collins Guest

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

    Please wrap your lines!
    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, Jun 25, 2012
  15. Myth__Buster

    James Kuyper Guest

    On 06/25/2012 04:14 PM, Myth__Buster wrote:
    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?

    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.
    James Kuyper, Jun 25, 2012
  16. Myth__Buster

    Myth__Buster Guest

    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. Hence, careshould be exercised before the allocated memory could be used. (On similarlines, the applicable alternative approaches can be mentioned therein to accomplish the same and thereby help the reader/programmer).

    Raghavan Santhanam
    Myth__Buster, Jun 25, 2012
  17. Myth__Buster

    Myth__Buster Guest

    *Completed my sentences.

    Myth__Buster, Jun 25, 2012
  18. Myth__Buster

    Ian Collins Guest

    Should it also caution that the return type of malloc is incompatible
    with int? with char? with ...
    Ian Collins, Jun 25, 2012
  19. 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:

    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, Jun 25, 2012
  20. Myth__Buster

    James Kuyper Guest

    On 06/25/2012 04:53 PM, Myth__Buster wrote:
    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.
    James Kuyper, Jun 25, 2012
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.