include chaos bewaeltigen



  • Hallo

    Ich bin noch neu und habe ein Stueck Software in C, wleches ich etwas umbauen
    soll. Jetzt habe ich ziemliche Probleme mit den .h Files und wie ich sie
    "include", ich bekomme die irrsinnigsten Fehlermeldungen und ich glaube einfach es
    liegt stark an der Reihenfolge. Das Problem ist irgendwie, dass ich in den .h
    Files include Anweisungen habe, die ich auch noch irgendwie ordnen kann, aber in
    den .c files auch. Irgendwie scheint das ganze nicht richtig zu kooperieren.

    Wo finde ich "Regeln", wie die include Anweisung genau arbeiten soll? Wie kann ich
    am besten vorgehen um eine neue "include-Struktur" aufzubauen? Gibt es evtl auch
    Tools unter Linux mit denen sich soetwas leichter bewerkstelligen laesst?
    ­čśĽ



  • Zeig mal den Code (also mit den include-Statements), von dem du denkst, dass er die Fehler verursacht, und vor allem die Fehlermeldungen.



  • Wenn Du einigerma├čen sauber arbeitest, sollte die Reihenfolge der Includes eigentlich keine Unterschiede machen. Theoretisch jedenfalls. ­čÖé

    Aber matze hat recht, zeig uns Deine Sourcen und wir sagen Dir, was Du falsch machst.



  • Hallo nochmal,

    Ersteinmal danke fuer die Antworten, schon klar, wenn ich sourcen praesentiere
    wird es leichter, aber so einfach ist es nicht. Ich werde versuchen etwas mehr
    Info zu geben.

    Meine momentane Aufgabe ist das Umbauen von schon vorhandenen sourcen. Die
    Sourcen stellen ein Projekt dar, das aus zwei externen Libraries besteht (mit
    denen ich keine Probleme habe und die ich auch nicht anruehre) und ca 60 - 80
    Codefiles. Prinzipiell ist der Code recht uebersichtlich. Ein Teil des
    Originacodes wurde per libtool in ein dynamisches .so umgebaut. Mein Ziel ist
    es jedoch das ganze nun monolithisch, also ohne dynamische verlinkung zu
    kompilieren. Ich habe also die entsprechenden Eintraege in den Makefile.am und
    configure.ac scripten soweit vorgenommen und es kompiliert auch. Nur, dass ich
    nun natuerlich auch entsprechende .h Files direkt includieren muss. Dabei fiel
    mir schon auf, dass die include Structur etwas oberflaechlich war, Teilweise
    wurden enums bzw. structs auch doppelt definiert und jeweils mit include guards
    auf dasselbe define geschuetzt, etc.. Was mir dabei dennoch fehlt ist einfach
    eine Strategie.

    Ich bin nun folgendermassen (mit einer Copie) vorgegangen:

    1. ich habe in den .c files alle includes geloescht bis auf die zum eignenen .h
    File

    2. ich habe in einem zentralen Headerfile, welches am anfang eingelesen werden
    soll, eine "Reihenfolge" an anderen .h Files festgelegt und includiert, damit
    "alles ersteinmal deklariert ist" (sein soll).

    3. dann habe ich anpassungen an anderen header Files vorgenommen und evtl.
    Eintraege aus dem initialen Headerfile geloescht.

    4. Nun kamen die Fehler in den .c Files und ich habe je nach fehlendem Typ nun
    entsprechende .h Files nach includiert.

    Mein Problem ist, nun habe ich teilweise "redundante includes", was eig auch
    kein Problem sein sollte wegen der Include Guards, aber irgendwo fehlt immer
    noch was. Die Fehlermeldungen reichen von "expected ')' before 'xyz'" bis
    "field 'asdf' has incomplete type" (ein echter Klassiker. Mir ist klar, dass
    die Zeilen absolut korrekt sind, nur fehlt einfach die Deklaration. Manchmal
    ist das so hartnaeckig, dass weder include noch forward declaration helfen,
    weil einfach in der Datei in dem der struct, enum oder sonst wie eig definiert
    ist, ein Fehler stecht, der manchmal auch nicht angezeigt wird, weil sich der
    Compiler evtl. vorher schon aufgehaengt hat(???).

    Es ist nervig und haarig. Mittlerweile habe ich als Tools nur den "include
    browser" der Eclipse C/C++ Edition und ein externes Tool den "Source Navigator"
    gefunden:

    http://sourcenav.sourceforge.net
    

    Leider gibt es den aber unter Debian nur auf oldstable (etch). Ich bin echt
    verzweifelt. Das Problem bestehenden Code aufzubereiten kann doch nicht so
    exotisch sein.

    Ich bin mir nicht ganz im klaren ob ich die include Anweisung ueberhaupt zu
    100% richtig verstehe. Afaik duerfte man doch GAR keine Fehler bekommen, sobald
    ein .h File irgendwo schon einmal includiert ist und einen include guard
    besitzt. Wie kann include ueberhaupt schief gehen?



  • Sieh dir mal "pragma once" und "ifndef" an.



  • Zu pragma once, ich bin auf Linux und arbeite mit gcc, zu ifndef - die .h Dateien HABEN include guards, also

    #ifndef _FOOBAR_H_
    #define _FOOBAR_H_
    // ...
    #endif
    

    deshalb verstehe ich ja nicht, warum trotzdem Fehler der Art: anscheinend hat er das File daten.h schon gelesen - irgendwann vorher - also wurde wohl auch das Symbol _DATEN_H_ gesetzt, weshalb kann er nun daten.h bei erneutem include in File xy.h nicht nochmal lesen kann. Gut, an das Symbol "_DATEN_H_" kann er sich also noch erinnern, und dass er es nicht nochmal lesen soll. Aber bei den Inhalt von daten.h hat er offensichlich nen Filmriss und deshalb sind ihm nun auch die Deklarationen in Datei xy.h wieder komplett unverstaendlich. Seufz.

    Kann mir einer erklaeren woran so ein Verhalten liegen kann? Wie ist soetwas MIT include Guards eigentlich moeglich in C? Ich habe da wirklcih ein Verstaendnisproblem, irgendwie.. ­čÖä



  • Bastel doch mal ein Minimal-Beispiel zusammen, dass den Fehler aufweist.



  • Hallo,

    Ja werde ich heute machen. Nach einigem ueberlegen gestern Nacht bin ich zu dem
    Entschluss gekommen, dass es nicht an der Sprache (C, bzw den includes) liegen
    kann. Sie sind eig richtig gesetzt. Ich habe ja ebenfalls in die Makestruktur
    eingegriffen und vermute einfach dort auch Fehler dieser Art.

    Ich werde nun versuchen einfach die Makefile.am Struktur Schritt fuer Schritt
    nachbauen. Sobald ich dort einen aehnlichen Fehler habe, werde ich es auf ein
    Minimalbeispiel reduziert hier praesentieren.



  • Die Fehler k├Ânnten auch auf Cross-Includes hindeuten, d.h. zwei oder mehr Header-Dateien binden sich gegenseitig ein - und da helfen dann auch keine Include-Guards mehr. (ebenfalls ein echter Klassiker -)



  • Wahrscheinlich ├╝bersehe ich gerade etwas Wichtiges, aber... Wenn ich das richtig verstehe geht es dir nur darum, die beiden Bibliotheken statisch statt dynamisch in dein Programm zu linken. Warum mu├čt du dazu ├╝berhaupt die Include-Struktur ver├Ąndern? Sollte es nicht reichen, nur die Makefiles etc. entsprechend anzupassen?

    Den Code aufzur├Ąumen ist nat├╝rlich trotzdem eine gute Sache, da will ich auch gar nicht gegen argumentieren.



  • Wenns an der Reihenfolge liegt, probiere es doch mal mit Forward Declaration.

    mal ein kleines beispiel

    A.h

    class B;  // Anstelle des einbindens von B.h wird dem compiler nur mitgeteilt, das es die klasse B gibt. 
    
    class A
    {
        B m_b;
    [...]
    }
    

    B.h

    class B;  // Anstelle des einbindens von A.h wird dem compiler nur mitgeteilt, das es die klasse A gibt. 
    
    class B
    {
        A m_a; 
    [...]
    }
    

    main.c

    #include "A.h"
    #include "B.h"
    
    int main( int argc, const char* argv[] )
    {
        [....]
    }
    

    Wenn du das ohne forward declaration mahchst bekommst du probleme, da a B braucht und B a. Ausserdem wird so das verarbeiten der Headerdateien stark beschleunigt.



  • Hui, vielen Dank fuer Euer Interesse!!!

    Cross-includes, ich glaube das trifft einen Teil meiner Probleme, diese
    versuche ich bereits mit Forward Declarations anzugehen, aber das scheint nicht
    mein einzigstes Problem zu sein.

    Frage:
    Oder, besser gesagt - wieso helfen bei Cross-includes eigentlich keine Include
    Guards?

    Ist die .h Datei schon vorher einmal gelesen, sollte der Inhalt dem Compiler
    doch bekannt sein, er kann sich ja auch daran erinnern dass er das mit
    #ifdef... #define xyz gesetze schon define-ed ist? Wieso entfaellt ihm aber
    dabei der Inhalt?

    Ein anderes Problem beschaeftigt sich generell mit einem anderen Ansatz,
    alternativ versuche ich nun statt mit einem autogen Script, mir ein eigenes
    Makefile zu schreiben, dabei habe ich ein allgemeineres Problem - werde dazu
    einen anderen Thread aufmachen.


Log in to reply