Compiler Macros = teh evil
-
Grade wieder ein super Beispiel gehabt, warum Makros direkt aus der Hölle kommen:
class PhysicsBody { public: void sleep(); };
Error: Not enough Parameters for macro sleep.
Etwas länger danach suchen müssen.
Das ganze war in einem Header einer lib. Die haben halt usleep (linux) und Sleep (Win32) gekapselt in einem doofen Makro. _
-
Scorcher24 schrieb:
Etwas länger danach suchen müssen.
Kann die IDE nicht zur Definition springen?
-
mngbd schrieb:
Kann die IDE nicht zur Definition springen?
Nicht bei Makros, da sie Text ersetzng sind.
Das ist wie als wenn du möchtest das du zu einem Search & Replace Springen möchtest was irgendwann vieleicht aufgerufen wird.
-
? In Visual Studio geht das.
-
Nicht bei Makros, da sie Text ersetzng sind.
Das ist wie als wenn du möchtest das du zu einem Search & Replace Springen möchtest was irgendwann vieleicht aufgerufen wird.Ich verstehe allerdings auch nicht was für die IDE so kompliziert sein soll, sie muss ja nur in allen eingebundenen Headern nach #define sleep suchen
-
Also in VAX kein Problem, der kennt alle Makros und springt auch dort hin. Und beim Eingeben von der Memberfunktion hätte er auch gleich das sleep-Makro vorgeschlagen, dann hätte man stutzig werden müssen.
Aber am Ende des Tages: ja, Makros are evil!
Bis auf die Bedingte Kompilierung fällt mir sonst nicht ein, wofür sie nützlich sein sollten. Weil Bedingte Kompilierung ist einfach nur genial.
-
Weil Bedingte Kompilierung ist einfach nur genial.
Genial? Wo ist da die Genialität?
Bis auf die Bedingte Kompilierung fällt mir sonst nicht ein, wofür sie nützlich sein sollten.
TMP kann halt auch nicht alle Probleme lösen. Mit Bedacht (!) eingesetzt sind Makros nützlich (z.B. BOOST_FOREACH).
-
Irgendwer schrieb:
TMP kann halt auch nicht alle Probleme lösen. Mit Bedacht (!) eingesetzt sind Makros nützlich (z.B. BOOST_FOREACH).
Nein, Makros wie BOOST_FOREACH zeigt nur eines: es gibt eine Schwäche in der Sprache! Lies mal Stroustrups Buch, der schreibt das selber klipp und klar, das der Einsatz von Makros nur die Schwäche der Sprache zeigen.
Und BOOST_FOREACH sagt nur, das wir ein richtiges foreach als Schlüsselwort brauchen.
-
Was musste hier denn gesucht werden? Dass es ein Makro namens sleep gibt steht in der Fehlermeldung. Du benennst dein Ding um und gut. Oder hast du tatsächlich den entsprechenden Header (ich nehme an der kommt nicht von dir, da der Thread sonst komplett unsinning wäre) geändert? Wenn ja, wie lange hast du gebraucht es zu finden? 5 Minuten? Das wirft natürlich jedes Projekt um
Kurz: Ich sehe das Problem nicht.
-
Artchi schrieb:
Lies mal Stroustrups Buch, der schreibt das selber klipp und klar, das der Einsatz von Makros nur die Schwäche der Sprache zeigen.
Und BOOST_FOREACH sagt nur, das wir ein richtiges foreach als Schlüsselwort brauchen.
Dann warten wie mal bis zum nächsten C++-Standard, vielleicht kommt es dann
-
Tim schrieb:
Kurz: Ich sehe das Problem nicht.
Das Problem bekommst du spätestens dann, wenn du keine der beiden Definitionen ändern kannst, die dort aufeinanderprallen, weil sie beide in externen Quellen stehen, die du nutzen willst (ich erinnere mich düster an Kollisionen zwischen std::min/std::max und den gleichnamigen Makros in der MFC).
-
Tim schrieb:
Was musste hier denn gesucht werden? Dass es ein Makro namens sleep gibt steht in der Fehlermeldung. Du benennst dein Ding um und gut. Oder hast du tatsächlich den entsprechenden Header (ich nehme an der kommt nicht von dir, da der Thread sonst komplett unsinning wäre) geändert? Wenn ja, wie lange hast du gebraucht es zu finden? 5 Minuten? Das wirft natürlich jedes Projekt um
Kurz: Ich sehe das Problem nicht.
Nein, ich hab die lib komplett rausgeworfen. Das zu ersetzen war nicht schwer. Nur es zeigt, trotz Namespace und Fokus in einer Klasse kann so nen Makro dein Naming zerschiessen.
Umbennen ist ja auch nicht die Lösung. Nacher gibts irgendwo ein anderes Makro das viel gravierender ist.Das größte Problem daran ist, dass man Makros nicht in einen Namespace packen kann.
Btw:
Das Makro ist auch in den Headern von MySQL vorhanden. Das hab ich über VA herausgefunden.
-
CStoll schrieb:
Tim schrieb:
Kurz: Ich sehe das Problem nicht.
Das Problem bekommst du spätestens dann, wenn du keine der beiden Definitionen ändern kannst, die dort aufeinanderprallen, weil sie beide in externen Quellen stehen, die du nutzen willst (ich erinnere mich düster an Kollisionen zwischen std::min/std::max und den gleichnamigen Makros in der MFC).
Das Problem hast du aber grundsätzlich bei gleichen Symbolnamen im selben namespace. Sicher, man kann entsprechend andere Namespaces benutzen, aber ebenso kann man Makros ein entsprechendes prefix mitgeben. Also kein primäres Makro-Problem, oder? Dass sleep kein guter Name für ein Makro ist unterschreibe ich sofort. Aber das als "Makros sind böse"-Argument zu benutzen finde ich fragwürdig.
-
Das Problem hast du aber grundsätzlich bei gleichen Symbolnamen im selben namespace
Und wie soll das zustande kommen? Wer für den eigenen Namespace 2 gleiche Symbole definiert, ist selber schuld. Wer in den Namespace von anderen schreibt, ebenfalls. Ausserdem kann man das immer noch selber beheben, indem man einfach drumrum nen anderen packt.
-
Scorcher24 schrieb:
Wer für den eigenen Namespace 2 gleiche Symbole definiert, ist selber schuld. Wer in den Namespace von anderen schreibt, ebenfalls.
Vollkommen richtig, aber die gleiche Argumentation gilt auch für Makros. Makro scheisse benamt? Makro scheisse.
-
Tim schrieb:
Dass sleep kein guter Name für ein Makro ist unterschreibe ich sofort. Aber das als "Makros sind böse"-Argument zu benutzen finde ich fragwürdig.
Da muss ich zustimmen. Leider verwenden einige Bibliotheken Allerweltsnamen für Makros, das geht natürlich gar nicht. Aber das ist erstens kein Problem der Makros selbst, sondern ihrer Programmierer, und kann zweitens leicht umgangen werden. Wenn man es sauber macht wie z.B. Boost, ist die Scopeverschmutzung überhaupt kein Problem mehr.
-
Normalerweise stehen in einem namespace auch nur Funktionen, die mehr oder weniger zusammengehören, d.h. der Autor einer Bibliothek weiß recht genau, welche Überladungen er für einen Namen vorgesehen hat und wie er damit umgehen kann.
Das Problem mit einem Makro ist, daß es keine Rücksicht auf Namensräume, Scope oder Programmstruktur ersetzt wird - wenn du ein#define min(x,y)...
stehen hast, wendet der Präprozessor diese Textersetzung auf jedes Vorkommen des Bezeichners min an, egal ob sich dahinter eine Funktion im Namensraum einer Bibliothek, die Methode einer Klasse oder eine Variable verbirgt. (wenn du Glück hast, bekommst du eine Meldung wie Scorcher, daß die Parameter nicht stimmen, wenn nicht, siehst du nur einen Syntax-Fehler der nicht wirklich zu dem erkennbaren Code passt)PS: Und auf die inhaltlichen Probleme, die (selbst an den richtigen Stellen) durch die sture Textersetzung des Präprozessors auf dich zukommen können, will ich gar nicht erst eingehen.
-
Artchi schrieb:
Irgendwer schrieb:
TMP kann halt auch nicht alle Probleme lösen. Mit Bedacht (!) eingesetzt sind Makros nützlich (z.B. BOOST_FOREACH).
Nein, Makros wie BOOST_FOREACH zeigt nur eines: es gibt eine Schwäche in der Sprache! Lies mal Stroustrups Buch, der schreibt das selber klipp und klar, das der Einsatz von Makros nur die Schwäche der Sprache zeigen.
Und BOOST_FOREACH sagt nur, das wir ein richtiges foreach als Schlüsselwort brauchen.
Sieh es doch mal so: jedes Ding hat Fehler/Schwächen etc. Viele davon findet man erst "zu spät".
Und etwas, das und hilft einige dieser Schwächen im Nachhinein auszubügeln oder wenigstens abzuschwächen (Schwächen abschwächen, hihi), ist gut.
Also sind Makros gut.So einfach ist das. Zumindest für mich.
ps:
Gurte sind scheisse, sie zeigen nur die Unzulänglichkeiten des Fahrers/der Welt.
Muaha
-
Wer GNU
gcc
nutzt, kann den C-Präprozessorcpp
direkt aufrufen und sich den Code angucken, so wie ihn der Compiler zu sehen bekommt, mit allen ersetzten Makros, ohne Kommentare usw. Vielleicht hilft es weiter, wenn man nicht weiterkommt.
Ob so was auch bei anderen Compilern oder IDEs gibt...
-
Das Problem ist ja gelöst.
Ich fand es nur so genial exemplarisch für einen Foreneintrag, weil es genau die Art von Makro ist, die man eben nicht schreiben soll. Natürlich sind Makros was tolles wenn man sie sinnvoll einsetzt. Ich nutze sie ja auch. Aber ich prefixe meine Makros und gebe denen sinnvolle Namen, so dass Duplikate schwer werden.