0

I'm working with function pointers in c because I need a callback mechanism for my custom API library. Summarizing with a simple example:

*userfunction*(SY_msg msg)
{
  /* do something */
};

The size of SY_msg is 1024 bytes. 1024 bytes are therefore in the stack.

A pointer to userfuncion() is present as first element in calback_wrapper[].

here is an example of use:
// (...) some code
    SY_msg* msg;
    msg = SYmalloc (sizeof(SY_msg)); /* it takes 1024 bytes in heap */
// (...) some code
    calback_wrapper[0] (*msg); /*  1204 are passed by value  */
    /* during userfunction() execution , 1024 unused bytes are present in the heap */
    free (msg); /* now finally heap is free */
// (...) some code

But I would like to have the following:

// (...) some code
    SY_msg* msg;
    msg = SYmalloc (sizeof(SY_msg)); /* it takes 1024 bytes in heap */
// (...) some code
    memcpy(someplace,msg,sizeof(SY_msg); /*  where "someplace" is a point in the stack referred by the argument of userfunction()  */
    free (msg); /*  heap is free */
    calback_wrapper[0] (*someplace); /* is starts userfunction() execution */
// (...) some code

It is possible to find "someplace" address? My compiler is gcc.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Why can't you simply leave allocation to the caller? – Lundin Nov 26 '18 at 11:57
  • `calback_wrapper[0] (*msg); /* 1204 are passed by value */` Can't you just pass `msg` instead of `*msg` and make the function expect a pointer instead of the whole data structure? As far as I understand it is your own API. You could change it. – Gerhardh Nov 26 '18 at 12:01
  • no I can't because who will free() msg? –  Nov 26 '18 at 13:11
  • The Memory management must be invisible to userfunction(). –  Nov 26 '18 at 13:13
  • userfunction() must simply receive the **msg** structure by value, –  Nov 26 '18 at 13:16
  • This issue seems not to be related to function pointers at all. – alk Nov 26 '18 at 13:46
  • I'm asking if is possible to find the address of the argument of a function , starting from the function pointer. –  Nov 26 '18 at 13:55
  • How, BTW is `SY_msg` defined? I assumed it to be a `struct`. – alk Nov 26 '18 at 13:57
  • The address of `msg` inside `userfunction()` is `&msg`, which is *not* known by the caller. – alk Nov 26 '18 at 13:58
  • @alk the caller knows the function pointer , which probably has a reference to msg I'm expecting userfunction() + offset = &msg . It depends on the compiler –  Nov 26 '18 at 14:03
  • This not just depends on the compiler but on its version and the platform. – alk Nov 26 '18 at 14:05

2 Answers2

0

What keeps from you doing

// (...) some code
SY_msg msg, * pmsg;
pmsg = SYmalloc (sizeof(SY_msg)); /* it takes 1024 bytes in heap */
// (...) some code using pmsg instead of msg
memcpy(&msg, pmsg, sizeof(SY_msg)); /*  where "someplace" is a point in the stack referred by the argument of userfunction()  */
free (pmsg); /*  heap is free */
calback_wrapper[0] (msg); /* is starts userfunction() execution */
// (...) some code

in the above example you can replace

memcpy(&msg, pmsg, sizeof(SY_msg));

by

msg = *pmsg;
alk
  • 69,737
  • 10
  • 105
  • 255
  • msg = 1024 bytes in stack –  Nov 26 '18 at 13:23
  • userfunction = 1024 bytes in stack –  Nov 26 '18 at 13:24
  • pmsg = 1024 bytes in heap –  Nov 26 '18 at 13:25
  • @Giorgio: You define the user-function to allocate 1024 bytes on the stack: `userfunction(SY_msg msg)`. If you do not want this, define it differently. – alk Nov 26 '18 at 13:27
  • Im looking for a clever way to save space in the stack. The optimal solution could be 1024 bytes in heap and 1024 bytes in the stack from the _userfunction()_. –  Nov 26 '18 at 13:28
  • @Giorgio: "*1024 bytes in heap and 1024 bytes in the stack from the userfunction()*" that is what your 1st snippet exactly does. – alk Nov 26 '18 at 13:34
  • I see your point. No way. To pass a `SY_msg` by value it needs to be dereferenced and with this allocated on the caller side to actually do the call. – alk Nov 26 '18 at 13:39
  • Yes it does , but in that case free (msg) will be executed only after the return of userfuncion() . This code is intended as part of a task of a RTOS. –  Nov 26 '18 at 13:40
  • If `userfunction()` is a long runner you could introduce some asynchronism here by. Would using threads be an option? – alk Nov 26 '18 at 13:42
0

There are wrong assumptions in my question. The argument of user function() is allocated in the stack just AFTER the function call. Maybe some kind of "contextswich" could solve this problem. Example:

  • Call userfunction();
  • "contextswich"
  • Free the heap
  • "contextswich"
  • Resume userfunction();

But in any case, an assembly code snippets is requested.