53 votes

Déterminer la fonction vers laquelle pointe un pointeur en C ?

J'ai un pointeur vers une fonction, avec une signature quelconque. Et j'ai 5 fonctions différentes avec la même signature.

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

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

65voto

nos Points 102226

Vous devrez vérifier à 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 un tableau 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);

27voto

janneb Points 17303

En général, en C, de telles choses ne sont pas à la disposition du programmeur.

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

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

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

16voto

Bathsheba Points 23209

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

C n'est pas un réflecteur la langue.

Soit vous maintenez une table des pointeurs de fonction avec leur nom, soit vous fournissez un mode de en appelant chaque fonction qui renvoie le nom.

15voto

Basile Starynkevitch Points 67055

Le débogueur pourrait vous le dire (c'est-à-dire le nom d'une fonction, étant donné son adresse).

La table des symboles d'un appareil non dénudé ELF pourrait également vous aider. Voir nm(1) , objdump(1) , readelf(1)

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

Bien sûr, si vous n'avez que cinq fonctions d'une signature donnée, vous pourriez comparer votre adresse (à leurs cinq adresses).

Remarquez que certaines fonctions n'ont pas de nom (globalement visible), par exemple static fonctions.

Et certaines fonctions pourraient être dlopen -ed et dlsym -(par exemple, à l'intérieur des plugins). Ou bien leur code est synthétisé au moment de l'exécution par un cadre JIT ( libjit , gccjit , LLVM , asmjit ). Et le compilateur optimisant peut (et fait !) des fonctions en ligne, clonez-les, appel de la queue etc.... donc votre question peut ne pas avoir de sens en général...

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

Mais en général, votre quête est impossible. Si vous avez vraiment besoin de telles informations réfléchies de manière fiable, gérez-les vous-même (consultez Le CAIA de Pitrat système à titre d'exemple, ou en quelque sorte mon MELT ), peut-être en générant du code pendant la construction.

13voto

Lundin Points 21616

Savoir où pointe un pointeur de fonction est une chose dont vous devrez tenir compte dans votre programme. Le plus courant est de déclarer un tableau de pointeurs de fonction et d'utiliser une variable int comme index de ce tableau.

Ceci étant dit, il est aujourd'hui également possible de savoir en cours d'exécution quelle fonction est actuellement exécutée, en utilisant la fonction __func__ identifiant :

#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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X