[C++] Function Tracker
Verfasst: 18.10.2010, 22:07
Hallo,
ich schreibe mir gerade einen Function Tacker, der mir alle augerufenen Funktionen in einem vektor speichert. Ich habe eine Klasse A, die den statischen vektor und die statischen Funktionen, um in den vektor zu schreiben und aus ihm elemente zu löschen, besitzt.
Daneben existiert eine Klasse B, die beim instanzieren im Konstruktor die statische Funktion zum speichern des Funktionsnamen von Klasse A aufruft und im Destruktor dann die statische Funktion von Klasse A aufruft, um den Funktionsnamen wieder zu löschen.
Wenn ich nun in einer Funktion eine Instanz von B erstelle, dann speichert er mir den Funktionsnamen im statischen Vektor. Beim Verlassen der Funktion wird die Instanz von B zerstört und der Funktionsname wird aus dem statischen Vektor gelöscht. Somit kann ich bei einer Exception mir die aufgerufenen Funktionen ausgeben lassen.
Diesen FunktionsTracker möchte in einer eigenen lib speichern, die ich dann in anderen eigenen libs verwende.
Zusätzlich will ich das Tracken in eigenen Projekten an und ausschalten. Wenn das Programm also erstmal fehlerfrei läuft, dann schalt ich den Tracker aus und spare somit ein wenig Rechenzeit und Speicher.
Meine Frage ist nun, wie ich das umsetzen kann?
Einerseits könnte man es mit Präprozessdirektiven in der FunctionTracker-Lib lösen
Das Problem hierbei ist aber, dass alle anderen Libs, die diese FunctionTracker-Lib einbinden das Makro track() wegoptimieren, wenn in der jeweiligen lib DEFINE_FUNCTIONTRACKER = 0 ist und bei DEFINE_FUNCTIONTRACKER = 1 es sich nicht im Projekt ausschalten lässt. D.h. wenn ich in meinem Projekt
definiere, aber die lib mit DEFINE_FUNCTIONTRACKER = 0 kompiliert wurde, dann wird nicht getrackt, obwohl es gewollt ist und umgekehrt.
Ein andere Lösung wäre mit Templates:
In der Klasse A würde eine statische Variable deklariert werden:
In allen Funktionen würde ich nun immer B<A::log>("...") instanzieren, um zu tracken. Bei A::log == true würde das Tracking stattfinden. Bei A::log == false würde kein Tracking stattfinden. Nun stellt sich mir aber die Frage, ob der Compiler B<false>("...") wegoptimiert?
Somit könnte ich zu Beginn eines jeden Projekts A::log setzen, um zu tracken (true) oder es sein zu lassen (false). Beim letzteren Fall (false) weiss ich aber nun nicht, ob die Instanzierung wegoptimiert wird, um somit Ressourcen und Rechnzeit zu sparen.
Weiss jemand, ob dies der Fall ist oder wie ich das sicher ermitteln kann oder hat vlt. jemand einen ganz anderen Ansatz?
ich schreibe mir gerade einen Function Tacker, der mir alle augerufenen Funktionen in einem vektor speichert. Ich habe eine Klasse A, die den statischen vektor und die statischen Funktionen, um in den vektor zu schreiben und aus ihm elemente zu löschen, besitzt.
Daneben existiert eine Klasse B, die beim instanzieren im Konstruktor die statische Funktion zum speichern des Funktionsnamen von Klasse A aufruft und im Destruktor dann die statische Funktion von Klasse A aufruft, um den Funktionsnamen wieder zu löschen.
Code: Alles auswählen
class A{
friend class B;
private:
static std::vector<const char*> _stringVectorGlobal;
static void _pushFunction(const char* l_FuncName);
static void _popFunction();
public:
A() {}
};
class B{
public:
B(const char* l_FuncName){
A::_pushFunction(l_FuncName);
}
~B(){
A::_popFunction();
}
};
Diesen FunktionsTracker möchte in einer eigenen lib speichern, die ich dann in anderen eigenen libs verwende.
Zusätzlich will ich das Tracken in eigenen Projekten an und ausschalten. Wenn das Programm also erstmal fehlerfrei läuft, dann schalt ich den Tracker aus und spare somit ein wenig Rechenzeit und Speicher.
Meine Frage ist nun, wie ich das umsetzen kann?
Einerseits könnte man es mit Präprozessdirektiven in der FunctionTracker-Lib lösen
Code: Alles auswählen
#if DEFINE_FUNCTIONTRACKER
#define track() static const char *INTERNAL_FUNCNAME = __FUNCTION__; \
B INTERNAL_TRACK(INTERNAL_FUNCNAME);
#else
#define track()
#endif
Code: Alles auswählen
#define DEFINE_FUNCTIONTRACKER 1
Ein andere Lösung wäre mit Templates:
Code: Alles auswählen
template <bool>
class B
{
public:
B( const char* l_FuncName ) : _param( l_FuncName ) { A::_pushFunction( l_FuncName ); }
~B() { A::_popFunction( l_FuncName); }
private:
const char* _FuncName;
};
template <>
class B <false>
{
public:
B( const char* l_FuncName) {}
~B() {}
};
Code: Alles auswählen
static bool A::log = true;
Somit könnte ich zu Beginn eines jeden Projekts A::log setzen, um zu tracken (true) oder es sein zu lassen (false). Beim letzteren Fall (false) weiss ich aber nun nicht, ob die Instanzierung wegoptimiert wird, um somit Ressourcen und Rechnzeit zu sparen.
Weiss jemand, ob dies der Fall ist oder wie ich das sicher ermitteln kann oder hat vlt. jemand einen ganz anderen Ansatz?