Search code examples
cstackpthreadsposixfunction-pointers

Copy Function Pointer to Block of Memory in C


I am working on implementing a threading library using the pthreads API. One of the things I need to do is allocate a stack of size 32767 bytes and then put the function pointer to pthread_exit at the top of the stack, and decrement the stack pointer to be below that function pointer.

The code I have come up with is as follows:

    void *stackPointer = malloc(32767);
    stackPointer += 32767;
    stackPointer -= sizeof(&pthread_exit);
    stackPointer = memcpy(stackPointer, pthread_exit, sizeof(&pthread_exit));

From what I can tell the function pointer is not properly placed in the memory by using the memcpy function in this way. Is there another way I should be going about this (or function I should be using)?

Edit: Fixed code to have stack pointer at the top from the start


Solution

  • There are a lot of suspicious things with the code presented. Among these are

    • it is non-conforming to do pointer arithmetic with pointers of type void *;
    • you appear to be discarding the only pointer to a dynamically-allocated block, making it tricky, if possible at all, to deallocate the block later; and
    • depending on how you intend to use it, it may be an issue that you do not ensure correct alignment of the value you are pushing on the stack.

    But those are comparatively small: some compilers do what you appear to want with void-pointer arithmetic, you may be able to recompute the pointer needed to deallocate the block, and maybe alignment isn't a concern for your purposes.

    However,

    From what I can tell the function pointer is not properly placed in the memory by using the memcpy function in this way.

    No, it definitely isn't. The memcpy() function copies the data pointed to by the source pointer to the location indicated by the destination pointer. You want to write the pointer itself, which is another matter altogether.

    Is there another way I should be going about this (or function I should be using)?

    You could store the pointer in a variable and then copy it from there:

    #define STACK_SIZE 32767
    
    void (*pte)(void *) = pthread_exit;
    
    void *stackLimit = malloc(STACK_SIZE);
    void *stackBottom = stackLimit + STACK_SIZE;
    void *stackPointer = (char *) stackBottom - sizeof(pte);
    
    memcpy(stackPointer, pte, sizeof(pte));
    

    Or if unaligned access were not an issue (or if a stack size a little more or less than 32767 were ok) then you could do it more simply with a plain assignment:

    void *stackLimit = malloc(STACK_SIZE);
    void *stackBottom = stackLimit + STACK_SIZE;
    typedef void (*pte_type)(void *);
    
    ((pte_type) stackBottom)[-1] = pthread_exit;
    void *stackPointer = (pte_type) stackBottom - 1;
    

    The typedef is for clarity and reading ease. Equivalent code could be written without.

    Note that expressions of function type, such as pthread_exit is when the declaration of that function is in scope, are automatically converted to function pointers. You don't need to use the & operator on them, though it's harmless to do so.