Wie können wir den Namen der aufrufenden Funktion erfahren?

Lesezeit: 5 Minuten

Benutzeravatar von Tom Xue
Tom Xue

In der C-Sprache __FUNCTION__ kann verwendet werden, um die zu erhalten aktuell Funktionsname. Aber wenn ich eine Funktion namens a() definiere und sie in b() aufgerufen wird, wie unten:

b()
{
    a();
}

Nun, im Quellcode gibt es viele Funktionen wie b(), die a() aufrufen, zB c(), d(), e()…

Ist es möglich, innerhalb von a() Code hinzuzufügen, um den Namen der Funktion zu erkennen, die a() aufgerufen hat?

Des Weiteren:

  1. Sorry für den irreführenden Tippfehler. Ich habe es korrigiert.
  2. Ich versuche herauszufinden, welche Funktion a() zu Debugging-Zwecken aufruft. Ich weiß nicht, wie es dir geht, wenn du in der gleichen Situation bist?
  3. Und mein Code ist unter vxWorks, aber ich bin mir nicht sicher, ob er mit C99 oder etwas anderem zusammenhängt.

  • Nicht sicher. Aber das ist vielleicht hilfreich für Sie

    – Suvarna Pattayil

    19. April 2013 um 8:10 Uhr

  • Warum willst du das tun? Ist es für Debugging-Zwecke?

    – fstamour

    19. April 2013 um 8:13 Uhr

  • Wenn dies nur zum Debuggen dient, können Sie a als Makro definieren und so verwenden __func__ wird b zurückgeben, wie Sie möchten.

    – Jo

    19. April 2013 um 8:15 Uhr


  • Welcher Compiler hat FUNKTION um den Namen der aktuellen Funktion zurückzugeben? Der dafür im C-Standard vorgesehene Bezeichner ist __func__ IIRC.

    – Jens Gustedt

    19. April 2013 um 8:18 Uhr


  • was du schreibst ist falsch. __FUNC__ gibt den aktuellen Methodennamen AFAIK zurück. Um den Anrufer zu erhalten, müssten Sie sich den Stacktrace ansehen

    – Daij-Djan

    19. April 2013 um 8:19 Uhr


Benutzeravatar von Didier Trosset
Didier Trosset

Es gibt nichts, was Sie nur in a tun können.

Mit einem einfachen Standard-Makrotrick können Sie jedoch erreichen, was Sie wollen, IIUC zeigt den Namen des Anrufers an.

void a()
{
    /* Your code */
}

void a_special( char const * caller_name )
{
    printf( "a was called from %s", caller_name );
    a();
}

#define a() a_special(__func__)

void b()
{
    a();
}

  • Ich musste die Variable caller_name als deklarieren const char* caller_nameaber es hat funktioniert!

    – roter Curry

    11. Februar 2014 um 18:33 Uhr

  • Präzision: __func__ ist Teil des C99-Standards, […] __FUNCTION__ ist ein anderer Name für __func__, bereitgestellt für die Abwärtskompatibilität mit alten Versionen von GCC. (Quelle: gcc.gnu.org/onlinedocs/gcc/Function-Names.html)

    – Camille G.

    2. Juni 2017 um 9:18 Uhr


  • Können Sie mir bitte sagen, wie ich Ihr Beispiel mit Auslassungspunkten in der Funktionsdeklaration verwenden kann? void a(int a, char *fmt, ...) Wie kann ich es in die Makrodefinition aufnehmen?

    – Alejandro Galera

    9. Januar 2019 um 12:56 Uhr

  • @mulg0r Schau mal rein va_list , va_arg und Gefährten. Ich bezweifle jedoch, dass Sie diesen Trick auf eine Funktion mit Auslassungszeichen anwenden können: Es sollte mit geschrieben werden va_list stattdessen, genau wie die vprintf Funktionsreihe 🙁

    – Didier Trosset

    10. Januar 2019 um 12:57 Uhr

  • @mulg0r Verwenden Variadische Makros Sie können erreichen, was Sie wollen (z.#define a(...) a_special (__func__, __VA_ARGS__)für eine Funktion void a_special(char const * caller_name, ...){}) Sie gibt es in C seit C99 und in C++ seit C++11.

    – Toto

    19. November 2019 um 14:17 Uhr


Vickys Benutzeravatar
Vicky

Sie können dies mit einem integrierten gcc tun.

void * __builtin_return_address(int level)

Der folgende Weg sollte den unmittelbaren Aufrufer einer Funktion a() ausgeben.

Beispiel:

a() {
    printf ("Caller name: %pS\n", __builtin_return_address(0));
}

  • Dies gibt die Rücksendeadresse aus (immer noch nützlich), aber nicht den Funktionsnamen.

    – dbrank0

    10. August 2018 um 7:26 Uhr

Wenn Sie ein Linux-System verwenden, können Sie die verwenden backtrace() Funktion.

Siehe die Manpage für weitere Details und ein Codebeispiel.

  • Ende 2020 ist es auch für macOS verfügbar.

    – Rostyslav Druschtschenko

    13. September 2020 um 15:00 Uhr

Benutzeravatar von alk
alk

Versuche dies:

void a(<all param declarations to a()>);

#ifdef DEBUG
#  define a(<all params to a()>) a_debug(<all params a()>, __FUNCTION__)
void a_debug(<all params to a()>, const char * calledby);
#endif

void b(void)
{
  a(<all values to a()>);
}

#ifdef DEBUG
#  undef a
#endif

void a(<all param declarations to a()>)
{
  printf("'%s' called\n", __FUNCTION__);
}

#ifdef DEBUG
void a_debug(<all param declarations to a()>, const char * calledby)
{
  printf("'%s' calledby '%s'", __FUNCTION__, calledby);
  a(<all params to a()>);
}
#endif

Wenn zum Beispiel <all param declarations to a()> ist int i, double d, void * p dann <all params to a()> ist i, d, p.


Oder (weniger böse ;->> – aber mehr Code-Modding, da jeder Aufruf von a() berührt werden muss):

void a((<all params of normal a()>    
#ifdef DEBUG
  , const char * calledby
#endif
  );

void a((<all params of normal a()>    
#ifdef DEBUG
  , const char * calledby
#endif
  )
{
#ifdef DEBUG
  printf("'%s' calledby '%s', __FUNCTION__, calledby);
#endif
  ...
}

...

void b(void)
{
    a(<all params of normal a()>
#ifdef DEBUG
      , __FUNC__
#endif
    );
}

__FUNCTION__ ist (zumindest?) auf GCC verfügbar, wenn Sie einen anderen C99-Compiler verwenden, ersetzen Sie ihn durch __func__.

Verweisen: https://www.gnu.org/software/libc/manual/html_node/Backtraces.html

Ein Backtrace ist eine Liste der Funktionsaufrufe, die derzeit in einem Thread aktiv sind. Der übliche Weg, einen Backtrace eines Programms zu untersuchen, ist die Verwendung eines externen Debuggers wie gdb. Manchmal ist es jedoch nützlich, einen Backtrace programmgesteuert innerhalb eines Programms zu erhalten, z. B. für Protokollierungs- oder Diagnosezwecke.

Die Header-Datei execinfo.h deklariert drei Funktionen, die Backtraces des aktuellen Threads erhalten und manipulieren.

Joes Benutzeravatar
Jo

Wenn Sie erst wissen möchten, wo Sie sich zu Protokollierungs-/Debugzwecken befunden haben, können Sie ein Makro verwenden, um dies zu vermeiden __func__ Angabe des Namens Ihrer Protokollierungs-/Debug-Funktion, aber der Funktion, die sie aufruft.

In einem Makro zu sein, führt nicht zu einer Änderung von __func__ aber “fühlen” sich an, als würden Sie eine Funktion verwenden.

z.B

#define LOG(s, data...) log("%s: "s, __function__, ## data)

Benutzeravatar von Dmitry Sazonov
Dmitri Sasonow

Wenn Ihre Plattform Windows ist, können Sie Folgendes verwenden: durch die Callstack gehen

1393730cookie-checkWie können wir den Namen der aufrufenden Funktion erfahren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy