2016-10-21 8 views
1

Ich möchte einige Objekte mit statischer Verknüpfung zusammen, ohne dass andere Daten verschachtelt. Die Objekte sind in separaten Quelldateien definiert. Die Reihenfolge spielt keine Rolle, solange sie zusammenhängend sind (mit Ausnahme von minimalem/Standard-Padding).Standard Weg statische Objekte zu setzen

In gcc kann ich das erreichen mit __attribute__((section("mydata"))), aber AFAIK das ist GCC spezifisch und nur viele Compiler unterstützen sie (gcc, llvm und ein paar andere, aber ich glaube nicht msvc), für viele Ziele (elf ja, andere Ich Ich bin mir nicht sicher, ich bezweifle es).

Q1: Gibt es einen Standardweg, um dies zu erreichen?

Q2: garantiert GCC, dass die Objekte zusammenhängend mit Padding sind? die Objekte können durch einen linearen Scan mit einem konstanten Schritt gezählt werden.

F3: gibt es einen Unterschied im Verhalten zwischen GCC und anderen Compilern, die dieses Attribut unterstützen?

Q4: Welche Ziele und wichtige Compiler würden dies nicht unterstützen?

Antwort

1

Es klingt wie Sie versuchen, plattformunabhängigen Code zu produzieren (daher die Notwendigkeit für einen Standardmechanismus) und während Sie Zugriff auf die Quelle haben, möchten Sie nur begrenzte Änderungen daran vornehmen. Die Lösung, die Sie vorschlagen, beinhaltet den Zugriff auf Datenstrukturen, die in mehreren Übersetzungseinheiten definiert sind, als wären sie Elemente eines einzelnen Arrays.

Q1. Weder die C standard noch die C++ standard enthalten das Konzept der Linkerabschnitte, also, nein, es gibt keine wirklich plattformunabhängige Möglichkeit, die Namen der Ausgabesektionen anzugeben.

Sie müssten nach jedem Compiler suchen, den Sie anvisieren möchten. Du hast die Beschwörungsformel für GCC und Clang bereits gefunden. Visual C++ hat #pragma section und __declspec(allocate), die zusammen dasselbe erreichen können.

Q2. GCC verwendet den Linker der Plattform, um eine ausführbare Datei zu erstellen. Unter der Annahme einer GNU-Umgebung wird dieser Linker die Binutils ld oder gold sein. Mit diesen Linkern ist jeder Ausgabeabschnitt zusammenhängend, und die Ausrichtung der Eingabeabschnitte innerhalb des Ausgabeabschnitts kann specified sein oder auf Standardwerte eingestellt sein. Gemäß der Dokumentation funktioniert die Standardeinstellung für Sie, wenn Sie davon ausgehen, dass alle Ihre Objektdateien mit derselben Version von GCC kompiliert wurden, wobei die gleichen Compileroptionen verwendet werden. Verschiedene Compileroptionen können zu unterschiedlichen Standardausrichtungen führen.

Q3. Hinsichtlich der Unterschiede im Verhalten auf Plattformen: Ihre Verwendung des Linkers ist ziemlich ungewöhnlich. Sie sollten jede Plattform, die Sie anvisieren, sorgfältig testen. Ich würde vorschlagen, eine kleine Binärdatei zu erstellen, die Objektdateien auf die von Ihnen gewünschte Weise zusammenfügt und (programmatisch) prüft, ob die Datenstrukturen in der von Ihnen gewünschten Weise zugänglich sind.

Q4. Es sieht so aus, als ob Ihr Ansatz für GCC/Clang/binutils unter Linux und für Visual C++/LINK unter Windows funktioniert. Es würde einige Anstrengungen erfordern, die Iosyncracies der einzelnen Plattformen zu lernen, aber ich denke, Sie könnten Ihren Ansatz auf fast jeder Post-1995-Plattform mit einer echten Tastatur anwenden. Möglicherweise haben Sie Schwierigkeiten mit älteren Maschinen und kleineren eingebetteten Systemen. Sie können es wahrscheinlich auf Android bekommen. Ich bin mir nicht sicher über iOS.

Als allgemeiner Hinweis ist der Zugriff auf Datenstrukturen durch die Annahme, dass sie über die Grenzen von Übersetzungseinheiten hinweg benachbart sind, ungewöhnlich. Sie werden wahrscheinlich in seltsame Probleme geraten und finden es schwierig, Hilfe zu bekommen.Hier sind einige alternative mechansims, die Sie vielleicht bekommen, was Sie wollen, mit weniger pro-Plattform Aufwand:

  1. Legen Sie die Quelldateien zusammen vor der Kompilierung und kompilieren sie als eine Einheit. Wenn es nicht manuell möglich ist, sollten Sie den Preprozessor verwenden oder ein kleines Perl- oder Python-Skript erstellen, um es zur Build-Zeit für Sie zu erstellen.

  2. Ordnen Sie zur Laufzeit dynamisch einen zusammenhängenden Speicherbereich zu und kopieren Sie die Datenstrukturen dorthin. Wenn die Datenstrukturen klein sind, wird dies nicht viel zusätzlichen Speicher benötigen. Wenn die Datenstrukturen groß sind, wird der Speicher, der die ursprünglichen Strukturen enthält, ausgelagert, und dies wird nicht viel zusätzlichen Speicher verbrauchen.

  3. Indirection verwenden: Ihr Programm greift auf die Datenstrukturen über ein Array von Zeigern auf die Daten zu.

Verwandte Themen