Logfile ohne Overhead
-
unskilled schrieb:
@volkard: sollte wegoptimiert werden ;o)
Ein Funktionsaufruf mit etlichen Syscalls drinne wird eher nicht wegoptimiert. Da würde ich mir keine Hoffnungen machen.
Je nach anwendungsgebiet kann man (worauf du sicherlich hinauswolltest.. ^^) aber auch komplett Makros nehmen - hat den Vorteil, dass man sich Variablennamen etc alles auf einmal einblenden lassen kann...
Oder auch mal #ifdef DEBUG im eigenen Code auftauchen lassen. Ist zwar wirklich nicht schön, aber es ist so einfach, daß sogar der Chef es versteht.
-
...
-
CSpille schrieb:
Da ist doch kein einziger Syscall drin...
Die sind nach Bearbeitung des Preprozessors doch schon raus, oder?debug(getLocalMachineDesription());Doch in getLocalMachineDesription()! Und die Funktion wird ausgewertet, um den string zu erzeugen, der der debug() übergeben wird. Daß die debug() dann den string ignoriert, kann nicht dafür sorgen, daß die getLocalMachineDesription() nicht aufgerufen wird.
Wegen einiger Syscalls, um eine Beschreibung der lokalen Maschine auszulesen und zusammnzubasteln, ist das Ding für den Compiler so seiteneffektbehaftet wie printf und wird wie auch printf-Aufrufe nicht nur deswegen wegoptimiert, weil man den Return-Wert nicht in weitere Berechnungen oder Ausgaben einfließen läßt.
-
...
-
hallo,
was würde gegen ein objektorientiertes design sprechen?
wäre sicherlich wartbarer und overhead dürfte auch nicht/unwesentlich erzeugt werden, wenn ich mich nicht irre.hier mal ein beispiel:
#include <string> #include <iostream> class Logger { public: virtual void log(std::string s) = 0; }; class DebugLogger : public Logger { public: void log(std::string s) { std::cout<<"debug logging:"<<s<<std::endl; } }; class ReleaseLogger : public Logger { public: void log(std::string s) { } }; int main() { static Logger* logger = new DebugLogger; // von config abhängig machen oder ähnliches ob new DebugLogger oder new ReleaseLogger logger->log("debuglogger"); }(kann mich auch irren - c++ eingerostet)
nur so eine idee
-
...
-
wow, hier geht's ja ab.
Interessantes Thema... Danke für die zahlreichen Antworten, scheint doch ein nicht ganz einfaches Thema zu sein.Würden sich alle an die Konvention halten, gäbe es viel seltener Probleme.
Gibt's diese Konvention irgendwo im Internet zum Nachlesen? Ich mache das nämlich auch (mehr oder weniger) frei Schnauze (und ja, ich weiß, dass das nicht gerade toll ist).

Grundsätzlich sollte einmal öffnen vollkommen ausreichen. Bei einem Absturz sollte das Betriebssystem zusehen, dass die Resourcen wieder freigegeben werden. Letztendlich kann man das mit Exception aber in den meisten Fällen dank der Destruktoren sogar selber erledigen.
Ich meinte damit eher, ob die Schreibzugriffe nicht mal durch einen Absturz verloren gehen könnten und dann die Message nicht im Log steht...
Kann sowas passieren oder sind diese ungepuffert? (dachte sie wären gepuffert)
Oder müsste man jedes mal ein flush nach dem Schreibzugriff einfügen?
-
Es gibt ungepufferte Streams.
std:cerrgehört z.B. dazu. Ergibt ja auch wie du richtig feststellst bei Log-Streams durchaus Sinn.
-
Ok, das löst das Problem natürlich... Vielen Dank

-
</Exit> schrieb:
Würden sich alle an die Konvention halten, gäbe es viel seltener Probleme.
Gibt's diese Konvention irgendwo im Internet zum Nachlesen? Ich mache das nämlich auch (mehr oder weniger) frei Schnauze (und ja, ich weiß, dass das nicht gerade toll ist).

Tja, den ersten Teil (Makros groß schreiben) findet man ganz klar, z.B. hier http://www.possibility.com/Cpp/CppCodingStandard.html (war die erste Seite die ich gefunden habe, über die Qualität kann ich nichts sagen).
Der zweite Teil (alles andere nicht komplett groß schreiben) folgt aus der Tatsache, dass man Kollisionen vermeiden will.
Lars
-
CSpille schrieb:
Ich bevorzuge dann aber
#ifdef DEBUG inline void debug(const std::string & debugMessage){ std::cout << debugMessage << std::endl; } #else inline void debug(const std::string & /*debugMessage*/){} #endifIch bevorzuge lieber:
namespace hidden { inline void debug(string const& file, string const& line, string const& function, string const& message) { out << function <<"@"<<file<<":"<<line<<" -> "<<message<<endl; } } #ifdef DEBUG #define DBG_OUT(msg) ((void)::hidden::debug(__FILE__, BOOST_STRINGIZE(__LINE__), BOOST_PRETTY_FUNCTION, (msg))) #else #define DBG_OUT(msg) ((void)0) #endif
-
Aber die __LINE__ vor der Ausgabe erst zum string zu machen, tut dem volkardchen weh.
Der Cast nach void des Ergebnisses von hidden::debug bewirkt gar nichts, oder?
-
volkard schrieb:
Aber die __LINE__ vor der Ausgabe erst zum string zu machen, tut dem volkardchen weh.
Kommt darauf an was man machen will. Hier ist die Umwandlung nicht notwendig und generell wären char const* wohl auch besser als string const&. Ich hab aber gerne line als String weil die Umwandlung gratis ist und man sich leichter tut das ganze in nicht c++ Streams reinzupacken.
Aber klar, __LINE__ kann man auch getrost so lassen wie es ist, das würde mich auch kein bisschen stören.
Der Cast nach void des Ergebnisses von hidden::debug bewirkt gar nichts, oder?
Jetzt wo du es sagst, ja.
-
Shade Of Mine schrieb:
Ich bevorzuge lieber:
namespace hidden { inline void debug(string const& file, string const& line, string const& function, string const& message) { out << function <<"@"<<file<<":"<<line<<" -> "<<message<<endl; } } #ifdef DEBUG #define DBG_OUT(msg) ((void)::hidden::debug(__FILE__, BOOST_STRINGIZE(__LINE__), BOOST_PRETTY_FUNCTION, (msg))) #else #define DBG_OUT(msg) ((void)0) #endifZu welchem Boost - Teil gehört BOOST_STRINGIZE und BOOST_PRETTY_FUNCTION? Google findet dazu nur diesen Thread.
-
Hi,
vielleicht könnte mir noch mal jemand helfen... Ich bekomme einen "mutliple definition of _instance" Error:
Logfile.hpp
class Logfile{ public: //Singleton Design Pattern static Logfile* getLogfile(); static Logfile* getLogfile(string name, bool append = false, unsigned long size = 4096); void closeLogfile(); inline void writeToLog(string message, const unsigned int loglevel){...} private: //for Singleton Logfile(); Logfile(const Logfile&); Logfile& operator=(const Logfile&); //for functionality Logfile(string name, bool append = true, unsigned long size = 4096); ~Logfile(); static Logfile* _instance; //... }; Logfile* Logfile::_instance = NULL;Sonst wird _instance nirgendwo angesprochen... (außer natürlich in getLogfile)
Logfile.cpp
Logfile* Logfile::getLogfile(){ //Singleton return _instance == NULL ? _instance = new Logfile("Logfile.txt") : _instance; }
-
...
-
Danke, allerdings bleibt der Fehler...

-
include guards hast du?!
Logfile* Logfile::getLogfile(){ //Singleton return _instance == NULL ? _instance = new Logfile("Logfile.txt") : _instance; }hmm.. bäh! : D
Logfile* Logfile::getLogfile() { if(_instance == NULL) _instance = new Logfile("Logfile.txt"); return _instance; }wenn man es andersrum schreibt und 2x auf NULL prüft, hat man es so gar thread-safe:
Logfile* Logfile::getLogfile() { if(_instance != NULL) return _instance; if(_instance == NULL) _instance = new Logfile("Logfile.txt"); return _instance; }da gabs mal irgendwo hier nen schönen link (mit ner sehr ausführlichen beschreibung zu diesem problem), allerdings hab ich den nicht mehr - vll weiß ja jmd anders, was ich meine und hat ihn noch und postet ihn...
bb
-
...
-
jo, natürlich noch nen lock zwischen die beiden ifs... ^^