Determining to which function a pointer is pointing in C?

CFunction Pointers

C Problem Overview


I have a pointer to function, assume any signature. And I have 5 different functions with same signature.

At run time one of them gets assigned to the pointer, and that function is called.

Without inserting any print statement in those functions, how can I come to know the name of function which the pointer currently points to?

C Solutions


Solution 1 - C

You will have to check which of your 5 functions your pointer points to:

if (func_ptr == my_function1) {
    puts("func_ptr points to my_function1");
} else if (func_ptr == my_function2) {
    puts("func_ptr points to my_function2");
} else if (func_ptr == my_function3) {
    puts("func_ptr points to my_function3");
} ... 

If this is a common pattern you need, then use a table of structs instead of a function pointer:

typedef void (*my_func)(int);

struct Function {
    my_func func;
    const char *func_name;
};

#define FUNC_ENTRY(function) {function, #function}

const Function func_table[] = {
    FUNC_ENTRY(function1),
    FUNC_ENTRY(function2),
    FUNC_ENTRY(function3),
    FUNC_ENTRY(function4),
    FUNC_ENTRY(function5)
}

struct Function *func = &func_table[3]; //instead of func_ptr = function4;

printf("Calling function %s\n", func->func_name);
func ->func(44); //instead of func_ptr(44);

Solution 2 - C

Generally, in C such things are not available to the programmer.

There might be system-specific ways of getting there by using debug symbols etc., but you probably don't want to depend on the presence of these for the program to function normally.

But, you can of course compare the value of the pointer to another value, e.g.

if (ptr_to_function == some_function)
    printf("Function pointer now points to some_function!\n");

Solution 3 - C

The function names will not be available at runtime.

C is not a reflective language.

Either maintain a table of function pointers keyed by their name, or supply a mode of calling each function that returns the name.

Solution 4 - C

The debugger could tell you that (i.e. the name of a function, given its address).

The symbol table of an unstripped ELF executable could also help. See nm(1), objdump(1), readelf(1)

Another Linux GNU/libc specific approach could be to use at runtime the dladdr(3) function. Assuming your program is nicely and dynamically linked (e.g. with -rdynamic), it can find the symbol name and the shared object path given some address (of a globally named function).

Of course, if you have only five functions of a given signature, you could compare your address (to the five addresses of them).

Notice that some functions don't have any ((globally visible) names, e.g. static functions.

And some functions could be dlopen-ed and dlsym-ed (e.g. inside plugins). Or their code be synthetized at runtime by some JIT-ing framework (libjit, gccjit, LLVM, asmjit). And the optimizing compiler can (and does!) inline functions, clone them, tail-call them, etc.... so your question might not make any sense in general...

See also backtrace(3) & Ian Taylor's libbacktrace inside GCC.

But in general, your quest is impossible. If you really need such reflective information in a reliable way, manage it yourself (look into Pitrat's CAIA system as an example, or somehow my MELT system), perhaps by generating some code during the build.

Solution 5 - C

To know where a function pointer points is something you'll have to keep track of with your program. Most common is to declare an array of function pointers and use an int variable as index of this array.

That being said, it is nowadays also possible to tell in runtime which function that is currently executed, by using the __func__ identifier:

#include <stdio.h>

typedef const char* func_t (void);

const char* foo (void)
{
  // do foo stuff
  return __func__;
}

const char* bar (void)
{
  // do bar stuff
  return __func__;
}

int main (void)
{
  func_t* fptr;

  fptr = foo;
  printf("%s executed\n", fptr());

  fptr = bar;
  printf("%s executed\n", fptr());

  return 0;
}

Output:

foo executed
bar executed

Solution 6 - C

Not at all - the symbolic name of the function disappears after compilation. Unlike a reflective language, C isn't aware of how its syntax elements were named by the programmer; especially, there's no "function lookup" by name after compilation.

You can of course have a "database" (e.g. an array) of function pointers that you can compare your current pointer to.

Solution 7 - C

This is utterly awful and non-portable, but assuming:

  1. You're on Linux or some similar, ELF-based system.
  2. You're using dynamic linking.
  3. The function is in a shared library or you used -rdynamic when linking.
  4. Probably a lot of other assumptions you shouldn't be making...

You can obtain the name of a function by passing its address to the nonstandard dladdr function.

Solution 8 - C

  1. set your linker to output a MAP file.
  2. pause the program
  3. inspect the address contained in the pointer.
  4. look up the address in the MAP file to find out which function is being pointed to.

Solution 9 - C

A pointer to a C function is an address, like any pointer. You can get the value from a debugger. You can cast the pointer to any integer type with enough bits to express it completely, and print it. Any compilation unit that can use the pointer, ie, has the function name in scope, can print the pointer values or compare them to a runtime variable, without touching anything inside the functions themselves.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSumitView Question on Stackoverflow
Solution 1 - CnosView Answer on Stackoverflow
Solution 2 - CjannebView Answer on Stackoverflow
Solution 3 - CBathshebaView Answer on Stackoverflow
Solution 4 - CBasile StarynkevitchView Answer on Stackoverflow
Solution 5 - CLundinView Answer on Stackoverflow
Solution 6 - CMarcus MüllerView Answer on Stackoverflow
Solution 7 - CR.. GitHub STOP HELPING ICEView Answer on Stackoverflow
Solution 8 - CMark ChView Answer on Stackoverflow
Solution 9 - CBill IVView Answer on Stackoverflow