web-dev-qa-db-fra.com

Déterminer à quelle fonction un pointeur pointe dans C?

J'ai un pointeur pour fonctionner, supposer n'importe quelle signature ..__ Et j'ai 5 fonctions différentes avec la même signature.

Au moment de l'exécution, l'un d'eux est affecté au pointeur et cette fonction est appelée.

Sans insérer d’instruction print dans ces fonctions, comment puis-je connaître le nom de la fonction vers laquelle le pointeur pointe actuellement?

53
Sumit

Vous devrez vérifier sur laquelle de vos 5 fonctions votre pointeur pointe:

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

S'il s'agit d'un modèle courant dont vous avez besoin, utilisez une table de structures au lieu d'un pointeur de fonction: 

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

Généralement, en C, de telles choses ne sont pas disponibles pour le programmeur.

Il peut y avoir des moyens spécifiques au système pour y arriver en utilisant des symboles de débogage, etc., mais vous ne voulez probablement pas dépendre de leur présence pour que le programme fonctionne normalement.

Mais vous pouvez bien sûr comparer la valeur du pointeur à une autre valeur, par exemple.

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

Les noms de fonction ne seront pas disponibles au moment de l'exécution.

C n'est pas un réfléchissant langage.

Vous pouvez soit maintenir une table de pointeurs de fonction avec leur nom, soit fournir un mode de appelant chaque fonction renvoyant le nom.

16
Bathsheba

Le débogueur peut vous dire que (c'est-à-dire le nom d'une fonction, en fonction de son adresse).

La table des symboles d’un exécutable ELF non séparé peut également aider. Voir nm (1) _, objdump (1) , readelf (1)

Une autre approche spécifique à Linux GNU/libc pourrait être d’utiliser la fonction dladdr (3) au moment de l’exécution. En supposant que votre programme soit lié correctement et dynamiquement (par exemple, avec -rdynamic), il peut trouver le nom du symbole et le chemin de l'objet partagé en fonction de l'adresse (d'une fonction nommée globalement).

Bien sûr, si vous n’avez que cinq fonctions d’une signature donnée, vous pouvez comparer votre adresse (aux cinq adresses correspondantes).

Notez que certaines fonctions n’ont pas de noms (visibles globalement), par exemple static.

Et certaines fonctions pourraient être dlopen- ed et dlsym- ed (par exemple, dans des plugins). Ou bien leur code doit être synthétisé à l'exécution par un framework JIT-ing (libjit, gccjit, LLVM, asmjit). Et les compilateurs optimiseurs peuvent (et font!) Des fonctions en ligne, les cloner, les appeler à la queue , etc., de sorte que votre question n’aurait aucun sens en général .. .

Voir aussi backtrace (3) } _ & libbacktrace de Ian Taylor à l'intérieur de GCC.

Mais en général, votre quête est impossible. Si vous avez réellement besoin de telles informations de réflexion de manière fiable, gérez-les vous-même (examinez le système CAIA de Pitrat comme exemple, ou d'une manière ou d'une autre mon système FUSION ) code pendant la construction.

15

Pour savoir où un pointeur de fonction pointe, vous devez effectuer le suivi avec votre programme. Le plus commun consiste à déclarer un tableau de pointeurs de fonction et à utiliser une variable int comme index de ce tableau.

Cela étant dit, il est également possible de dire au runtime quelle fonction est actuellement exécutée, en utilisant l'identifiant __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;
}

Sortie:

foo executed
bar executed
13
Lundin

Pas du tout - le nom symbolique de la fonction disparaît après la compilation. Contrairement à un langage de réflexion, C ne sait pas comment ses éléments de syntaxe ont été nommés par le programmeur; en particulier, il n'y a pas de "recherche de fonction" par nom après la compilation.

Vous pouvez bien sûr avoir une "base de données" (par exemple un tableau) de pointeurs de fonction auxquels vous pouvez comparer votre pointeur actuel.

10
Marcus Müller

Ceci est tout à fait horrible et non-portable, mais en supposant:

  1. Vous êtes sur Linux ou sur un système similaire basé sur ELF.
  2. Vous utilisez des liens dynamiques.
  3. La fonction est dans une bibliothèque partagée ou vous avez utilisé -rdynamic lors de la liaison.
  4. Probablement beaucoup d'autres hypothèses que vous ne devriez pas faire ...

Vous pouvez obtenir le nom d'une fonction en transmettant son adresse à la fonction dladdr non standard.

8
R..
  1. paramétrez votre éditeur de liens pour générer un fichier MAP.
  2. mettre en pause le programme
  3. inspecter l'adresse contenue dans le pointeur.
  4. recherchez l'adresse dans le fichier MAP pour savoir quelle fonction est pointée.
3
Mark Ch

Un pointeur sur une fonction C est une adresse, comme n'importe quel pointeur. Vous pouvez obtenir la valeur d'un débogueur. Vous pouvez convertir le pointeur en n'importe quel type entier avec suffisamment de bits pour l'exprimer complètement et l'imprimer. Toute unité de compilation pouvant utiliser le pointeur, c'est-à-dire ayant le nom de la fonction dans l'étendue, peut imprimer les valeurs du pointeur ou les comparer à une variable d'exécution, sans rien toucher à l'intérieur des fonctions.

0
Bill IV