2016-07-25 9 views
0

Ich habe an einigen etablierten C++ - Projekten gearbeitet, die statische Variablen aus einer gemeinsam genutzten Bibliothek verwenden, um Parameter zu speichern. Bei der Kompilierung mit g++ oder clang++ wird die statische Variable für das gesamte Programm freigegeben (hat den gleichen Speicherort). Wenn sie jedoch mit Xcode kompiliert wird, hat die statische Funktionsvariable main einen anderen Speicherort als die statische Variable der gemeinsam genutzten Bibliothek. Gibt es eine Möglichkeit, Xcode zu kompilieren/den Code wie g++ oder clang++ zu kompilieren, während noch mit Xcode debuggen zu können?Xcode teilt keine statische Variable mit einer gemeinsam genutzten Bibliothek

Bitte siehe Beispiel unten:

main.cpp:

#include <iostream> 
#include "Params.hpp" 

int main(int argc, const char * argv[]) { 
    Params param = Params(); 
    param.addParams(); 
    std::vector<int> vi = Params::ParamsObj(); 
    vi.push_back(10); 
    for(std::vector<int>::iterator it = vi.begin(); it != vi.end(); ++it) { 
      std::cout << "i = " << *it << std::endl; 
    } 
    return 0; 
} 

Params.hpp:

#ifndef Params_hpp 
#define Params_hpp 

#include <vector> 

class Params{ 
    typedef std::vector<int> ParamVector; 
public: 
    static ParamVector& ParamsObj() { 
     static ParamVector m; 
     return m; 
    } 
    void addParams(); 
}; 

#endif /* Params_hpp */ 

Params.cpp:

#include "Params.hpp" 

void Params::addParams(){ 
    Params::ParamsObj().push_back(5); 
} 

Makefile:

clang: 
    clang++ -dynamiclib Params.cpp -o libshared_clang.dylib 
    clang++ main.cpp -o main_clang ./libshared_clang.dylib 

gpp: 
    g++-mp-4.9 -Wall -shared -fPIC -o libshared_gpp.so Params.cpp 
    g++-mp-4.9 -Wall -o main_gpp main.cpp ./libshared_gpp.so 

Ausgabe von beiden g++ und clang++ ist:

i = 5 
i = 10 

Während Xcode nur i = 10 ausgibt.

Wenn ich keine gemeinsam genutzte Bibliothek verwende und alles in eine Binärdatei kompiliere, gibt Xcode beide print-Anweisungen korrekt aus.

Meine aktuelle Lösung ist das Projekt main Funktion in seine eigenen gemeinsamen Bibliothek hinzufügen und dann eine Xcode bestimmte Datei erstellen, die lediglich ruft die main Funktion in der neu geschaffenen gemeinsamen Bibliothek. Ich hoffte jedoch auf eine Lösung, bei der der Code des zugrunde liegenden Projekts nicht geändert werden musste.

Antwort

1

Ich bin mir ziemlich sicher, dass wenn Sie Optimalisierung für gcc/clang einschalten (was Sie in Ihrem Beispiel nicht getan haben), werden sie das gleiche Verhalten wie Ihre Compilation mit XCode (das ist kein Compiler, aber ein IDE).

Ihr Problem ist, dass die ParamsObj() Funktion inline ist (in der Klasse Körper definiert, fügt ein implizites inline Schlüsselwort, um es), so dass der Compiler nur „Einfügen“ in die main Methode, anstatt sie zu rufen.

Mit DLL-Grenzen kann dies zur Zuweisung mehrerer statischer Variablen führen, wenn die Funktion in mehreren Bibliotheken verwendet wird (in Ihrem Fall wird es in der DLL verwendet und in die Hauptdatei integriert).

Refactor die ParamsObj() Methode in eine Deklaration und eine separate Definition in der entsprechenden C++ - Datei, und Sie werden überall das gleiche Verhalten, Drucken von beiden Zahlen.

+0

Das Hinzufügen von Optimierungen ('-O3' oder' -O2') ändert nichts am Verhalten. Wie ich in der Frage erwähnt habe, ist der Code, mit dem ich arbeite, ein Teil von großen etablierten Projekten. Daher würde ich es vorziehen, das Parameter-Objekt für diese Projekte nicht zu refaktorisieren. Ich verstehe, dass Xcode eine IDE ist, aber (von dem, was ich verstehe) verwendet es seinen eigenen Compiler, auf den ich mich beziehen wollte. – Kyle

+0

Refactoring bedeutet nur, dass die Implementierung einer Methode in eine andere Datei verschoben wird. Ich denke nicht, dass es eine große Veränderung ist, wenn das Problem behoben wird. Oder Sie könnten versuchen, '__attribute __ ((noinline))' 'zur Funktion hinzuzufügen, wenn der Compiler von XCode dies unterstützt. Selbst wenn es momentan funktioniert, garantiert nichts, dass diese Art von Code auf allen Plattformen funktioniert. – Dutow

+0

Danke für die Hilfe. Durch das Verschieben der Methode 'ParamsObj()', wie Sie es vorgeschlagen haben, wurde das Problem behoben. Alternativ funktioniert '__attribute __ ((noinline))' 'nicht mit Xcode,' __attribute __ ((visibility ("default"))) 'funktioniert und ist einfacher als das Umordnen des Codes. Ich fand auch, dass "Inline-Methoden versteckt" in den Xcode "Build-Einstellungen" gesetzt werden kann, um einen ähnlichen Effekt zu erhalten. Ich fand diese [Seite] (https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html) nützlich, wenn ich das hier untersuche. – Kyle

Verwandte Themen