2012-06-24 3 views
6

Gibt es eine Möglichkeit, GCC zu sagen, ein bestimmtes globales Array nicht auf Null zu initialisieren?GCC zwingen, bestimmte Globals auf Null zu setzen

Ich möchte zum Speichern einer großen Datenstruktur, die mein Code verwaltet, einen großen Teil des Speichers reservieren, so sage ich:

#define SIZE_16_MB 0x01000000 
BYTE mChunkSpace[SIZE_16_MB]; 

Das Problem, dass crtinit ist() eine Million Jahre dauert, um diesen Raum zu initialisieren zu Null, und es ist überhaupt nicht notwendig.

Gibt es eine Möglichkeit, ich kann es zwingen, diesen Raum nicht zu initialisieren?

Momentan bin ich hart codieren eine Speicheradresse, die außerhalb ist, was der Linker weiß, aber das ist keine besonders robuste Art, Dinge zu tun.

Zusätzlich ist dies ein langsamer Embedded-Prozess (50 MHz Microblaze), also nicht davon ausgehen, dass ich über einen PC spreche. Es dauert wirklich lange, diesen Raum auf Null zu setzen.

Antwort

6

Sie können die Attribute gcc verwenden, um das Objekt in einem anderen neuen Speicherabschnitt zu speichern, z. B. im Speicherbereich .noinit.

BYTE mChunkSpace[SIZE_16_MB] __attribute__ ((section (".noinit"))); 
+0

Ich bin selbst darüber gestolpert, aber es fiel mir schwer herauszufinden, wie genau es umgesetzt wird und ob es dem OP auf seiner Zielplattform zur Verfügung stehen würde. Von dem, was ich sagen kann, wird eine '.noinit' Sektion im' .bss' Bereich erstellt. Bedeutet das, dass es nicht null initialisiert * ist und nicht ~ 16MB Speicherplatz in der ausführbaren Datei belegt? –

+0

@EdS. "size -A -x" zeigt mir, dass die Adressen des Speicherbereichs sich von den Adressen des '.bss'-Bereichs unterscheiden. – ouah

+0

Ich wiederhole, was ich hier lese: http://www.nongnu.org/avr-libc/user-manual/mem_sections.html –

-2

Der Standard besagt, dass statische Daten, die zum Zeitpunkt der Deklaration nicht explizit initialisiert werden, auf Null initialisiert werden. Sie können Laufzeit Initialisierung vermeiden, indem das erste Element auf einen Wert ungleich Null initialisiert sich selbst:

#define SIZE_16_MB 0x01000000 
BYTE mChunkSpace[SIZE_16_MB] = {1}; 

Beachten Sie, dass, wenn Sie 0 angeben, wird der Compiler wahrscheinlich speichern Sie es nur in der .bss Abschnitt sowieso, das heißt, es wird zur Laufzeit noch initialisiert werden. Es muss das nicht tun, aber es wäre dumm das nicht zu tun. Jetzt wird Ihr Array in das .data Segment geworfen.

Natürlich wird dies die resultierende ausführbare Datei viel größer machen (~ 16MB größer, um genau zu sein), aber der Speicher wird zur Laufzeit nicht initialisiert. Die Frage hängt also davon ab, was dir zusteht. die Zeit, die benötigt wird, um diesen Speicher oder die resultierende ausführbare Größe auf Null zu setzen?

+0

Entschuldigung für diesen nicht-konstruktiven Kommentar-Ich habe keine gute Lösung, fast hätte ich vorgeschlagen, 'mChunkSpace' eine lokale von' main() ', als einen Witz, aber es ist unwahrscheinlich, in der Praxis zu arbeiten. Wie auch immer, wenn Sie sagen "aber der Speicher wird zur Laufzeit nicht initialisiert": er wird stattdessen aus dem permanenten Speicher geladen. Dies wird wahrscheinlich nicht schneller sein. –

+1

Sie können steuern, ob gcc Null-initialisierte Variablen in .bss mit dem Flag -f [no-] zero-initialized-in-bss einfügt. Der Standardwert ist -fzero-initialisiert-in-bss –

+0

@PascalCuoq: Kaum konstruktiv! Ich halte das für sehr konstruktiv, da ich das überhaupt nicht berücksichtigt habe. –

4

Versuchen dynamische Initialisierung:

BYTE* mChunkSpace = (BYTE*)malloc(SIZE_16_MB * sizeof(BYTE)); 

Dann werden diese Daten nicht initialisiert und wartet auf Sie es zu initialisieren.

+0

Das ist eine gute Lösung, aber es würde bedeuten, mein Heap-Segment viel größer zu machen. Das kann in Ordnung sein, wenn es die Leistung des Heapspeichers in anderen Kontexten nicht beeinträchtigt. – NXT

0

Ich würde eigentlich denken, dass nicht-statische Speicher standardmäßig nicht auf Null initialisiert ist?

+1

Objekte, die im Dateibereich definiert sind, haben eine statische Speicherdauer und werden daher auf Null initialisiert. – ouah

+0

Dies ist überhaupt nicht wahr (ist es eine Frage oder Aussage?). Glauben Sie, dass "i" im folgenden Code auf "0" initialisiert wird?'int main() {int ich; zurückgeben 0; } ' –

+0

Ich nehme an, ich * könnte * es auf den Stapel legen und einen Zeiger darauf in einem globalen speichern, aber das scheint wirklich wie ein Missbrauch des Stapels. :-) – NXT

2

Die meisten Antworten, die Sie hier auf SO erhalten, werden in Richtung Visual Studio oder GCC geneigt sein, sowohl auf allgemeinen Plattformen (dh PCs, ob Windows oder Linux), als auch auf dem Standard. . "Zitate, von denen keine so viel für kleine eingebettete Systeme gilt, es sei denn, Sie haben Embedded Linux oder Windows CE ausgeführt.

ouahs Antwort ist wahrscheinlich am nächsten zu dem, was Sie brauchen ... vielleicht GENAU, was Sie brauchen, wenn Sie wirklich GCC verwenden. Da der von Ihnen gewünschte Speicherbereich sehr groß ist und wahrscheinlich den Löwenanteil des Speichers Ihres Systems verbraucht, sollten Sie einen speziellen Abschnitt in der Linker-Befehlsdatei Ihres Builds oder durch Linker-Anweisungen in einer C-, C++ - oder Assemblydatei definieren . Die Syntax hierfür variiert je nach Compiler. Wenn Sie Linker-Anweisungen in einer Quell-/Assemblydatei verwenden, müssen Sie wahrscheinlich Attribute angeben, die die Lese-/Schreibfähigkeit der Speicherregion usw. betreffen.oder vielleicht auch nicht, wenn die Microblaze keinen MMU/Speicher-Controller hat. Sie müssen ein Linker-Symbol am Anfang des Abschnitts einfügen und in Ihrem C-Code eine "extern char symName []" - Anweisung verwenden, damit Ihr C-Code in Relokationen kompilieren kann, die der Linker mit der tatsächlichen Adresse von die Sektion. Je nach Compiler und Architektur müssen Sie möglicherweise auch den symName [] extern mit einer Art "far" -Attribut deklarieren; Ich weiß nicht genug über die Microblaze, um etwas dazu zu sagen.

Verwandte Themen