Подтвердить что ты не робот

Определяет, какая функция указатель указывает на C?

У меня есть указатель на функцию, предполагаю любую подпись. И у меня есть 5 различных функций с одинаковой подписью.

Во время выполнения один из них назначается указателю, и эта функция вызывается.

Не вставляя какой-либо оператор печати в эти функции, как я могу узнать имя функции, на которую указывает указатель?

4b9b3361

Ответ 1

Вам нужно будет проверить, какие из 5 функций указывают ваш указатель:

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");
} ... 

Если это общий шаблон, который вам нужен, используйте таблицу структур вместо указателя функции:

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);

Ответ 2

Как правило, в C такие вещи недоступны программисту.

Могут существовать системные способы доступа туда, используя символы отладки и т.д., но вы, вероятно, не хотите зависеть от их наличия для нормальной работы программы.

Но вы можете, конечно, сравнить значение указателя с другим значением, например.

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

Ответ 3

Имена функций не будут доступны во время выполнения.

C не является отражающим языком.

Либо сохранить таблицу указателей функций с помощью имени, либо предоставить режим вызова каждой функции, которая возвращает имя.

Ответ 4

Отладчик может сказать вам, что (например, имя функции, учитывая ее адрес).

Символьная таблица исполняемого файла ELF также может помочь. См. nm (1), objdump (1), readelf (1)

Другим подходом Linux GNU/libc может быть использование во время выполнения функции dladdr (3). Предполагая, что ваша программа красиво и динамически связана (например, с -rdynamic), она может найти имя символа и путь к общему объекту с учетом некоторого адреса (функции, названной глобально).

Конечно, если у вас есть только пять функций данной подписи, вы можете сравнить свой адрес (с пятью адресами из них).

Обратите внимание, что некоторые функции не имеют ((глобально видимых) имен, например функций static.

И некоторые функции могут быть dlopen -ed и dlsym -ed (например, внутри плагинов). Или их код синтезируется во время выполнения некоторой структурой JIT-ing (libjit, gccjit, LLVM, asmjit). И оптимизирующий компилятор может (и делает!) Встроенные функции, клонировать их, tail-call их и т.д., поэтому ваш вопрос может вообще не иметь никакого смысла...

См. также backtrace (3) и Ian Taylor libbacktrace внутри GCC.

Но в целом ваш квест невозможно. Если вам действительно нужна такая отражающая информация надежным способом, управляйте ею самостоятельно (посмотрите на систему Pitrat CAIA в качестве примера, или как-то мой MELT), возможно, генерируя некоторый код во время сборки.

Ответ 5

Чтобы узнать, где указывает указатель на функцию, вы должны будете отслеживать свою программу. Наиболее распространенным является объявление массива указателей на функции и использование переменной int в качестве индекса этого массива.

В настоящее время также можно сказать во время выполнения ту функцию, которая выполняется в данный момент, с помощью идентификатора __func__:

#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;
}

Вывод:

foo executed
bar executed

Ответ 6

Совсем нет - символическое имя функции исчезает после компиляции. В отличие от рефлексивного языка, C не знает, как его синтаксические элементы были названы программистом; особенно, нет никакого "поиска функции" по имени после компиляции.

Конечно, у вас может быть "база данных" (например, массив) указателей на функции, с помощью которой вы можете сравнить свой текущий указатель.

Ответ 7

Это совершенно ужасно и не переносимо, но при условии:

  • Вы находитесь в Linux или какой-то подобной системе на базе ELF.
  • Вы используете динамическую компоновку.
  • Функция находится в общей библиотеке или вы использовали -rdynamic при связывании.
  • Наверное, многие другие предположения, которые вы не должны делать...

Вы можете получить имя функции, передав ее адрес нестандартной dladdr функции.

Ответ 8

  • установите ваш компоновщик для вывода файла MAP.
  • приостановить программу
  • проверить адрес, содержащийся в указателе.
  • найдите адрес в файле MAP, чтобы узнать, на какую функцию указывают.

Ответ 9

Указатель на функцию C - это адрес, как любой указатель. Вы можете получить значение из отладчика. Вы можете наложить указатель на любой целочисленный тип с достаточным количеством бит, чтобы выразить его полностью, и распечатать его. Любой блок компиляции, который может использовать указатель, т.е. Имеет имя функции в области видимости, может печатать значения указателя или сравнивать их с переменной времени выполнения, не затрагивая ничего внутри самих функций.