Forum: Compiler & IDEs NULL in bare metal system


von Daniel G. (motello)


Lesenswert?

Hallo,

ich möchte NULL in meinem bare metal programm (ohne BS) nutzen. Ich 
benutze newlib. Wenn ich string.h einbinde, ist auch ein NULL pointer 
definiert. Kann ich den bedenkenlos nutzen? wohin zeigt er?

toolchain: codesouercery

Grüße
Daniel

von Karl H. (kbuchegg)


Lesenswert?

Daniel G. schrieb:
> Hallo,
>
> ich möchte NULL in meinem bare metal programm (ohne BS) nutzen. Ich
> benutze newlib. Wenn ich string.h einbinde, ist auch ein NULL pointer
> definiert. Kann ich den bedenkenlos nutzen?

Mit einem NULL kann man eigentlich nur eines tun: Anzeigen, dass der 
Pointer nirgendwo Sinnvolles hinzeigt.

> wohin zeigt er?

Nirgendwo hin.

von Daniel G. (motello)


Lesenswert?

"Nirgendwo" liegt aber nicht im Bereich von 32bit Variablen. Kann ich 
ihn bedenkenlos nutzen? (Um eben keinen gültigen Pointer sondern "kein 
pointer" zurückzugeben)?

Ist NULL vielleicht immer als (void*) 0 deklariert?

von (prx) A. K. (prx)


Lesenswert?

Dieser Pointer zeigt auf ein C Handbuch. Dass du evtl. mal lesen 
solltest.

von Karl H. (kbuchegg)


Lesenswert?

Daniel G. schrieb:

> Ist NULL vielleicht immer als (void*) 0 deklariert?

Definiert!

Ja, das ist es.

Selbst dann, wenn an der Speicherzelle 0 bedenkenlos geschrieben/gelesen 
werden kann :-)

von BimmyundJimmy (Gast)


Lesenswert?

> Ist NULL vielleicht immer als (void*) 0 deklariert?

Nein! Laut C-Standard ist das nicht zwingend!
Ich meine, dies ist auch in dem Buch "Von C zu C" erwähnt!

von Karl H. (kbuchegg)


Lesenswert?

BimmyundJimmy schrieb:
>> Ist NULL vielleicht immer als (void*) 0 deklariert?
>
> Nein! Laut C-Standard ist das nicht zwingend!

Du hast recht, der void cast wird nicht gefordert. In C++ ist er sogar 
explizit verboten.

Aber der 'ungültige Pointer' hat immer für den C-Programmierer den 
Zahlenwert 0. Ob er das intern auch hat, ist Sache des Compilers. Für 
dich als C-Programmierer ist jeder Ausdruck der 0 ergibt ein vollkommen 
gültiger 'Pointer ins Nirgendwo'

> Ich meine, dies ist auch in dem Buch "Von C zu C" erwähnt!

Schön.
Schreib einen Bugbericht an den Autor und verweise ihn auf den 
Sprachstandard.

von Horst (Gast)


Lesenswert?

>> Kann ich ihn bedenkenlos nutzen? (Um eben keinen gültigen Pointer sondern
>> "kein pointer" zurückzugeben)?

Nein. Aber du kannst ihn nutzen, um einen als ungültig erkennbaren 
Pointer zurückzugeben.
Es ist aber immer noch ein Pointer, der auch verwendet werden kann wie 
jeder andere Pointer auch. Nur sinnvoll ist es halt nicht.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Nur sinnvoll ist es halt nicht.

Es sei denn, es liegt RAM an der Adresse 0 und man möchte darauf 
zugreifen.

So etwas macht man aber i.d.R. nicht aus C-Programmen heraus.

von (prx) A. K. (prx)


Lesenswert?

Es gab mal eine ganz üble Plattform für sowas. Eine Architektur mit 
vorzeichenbehaftetem Adressraum, also bei den 16bit-Versionen von 
-0x8000 bis +0x7FFF (INMOS Transputer T212). Da war kaum zu verhindern, 
dass 0 genau mittem im Speicher liegt. Bei den 32bit-Versionen war das 
zwar auch so, aber damals kein Problem.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Hallo!

Rufus t. Firefly schrieb:
> Es sei denn, es liegt RAM an der Adresse 0 und man möchte darauf
> zugreifen.

Es gibt dann aber auch noch solche Dep..., ähh merkbefreiten
Entwickler, die bei einer NULL-Pointer-Zuweisung schreiben:

int * a;

a = *NULL;

statt

a = NULL;

Da es leider etliche solcher Fälle gibt, wurde bei Solaris eine
Bibliothek namens lib0@0.so (oder so ähnlich) eingeführt, die nichts
anderes enthält als den Speicherinhalt 0x00000000 bzw 0x0000000000000000
an Adresse 0. Somit erhält a dann keinen anderen Wert als 0.

Vor etlichen Jahren fand ich bei einem ARM7-basierten Projekt einen
kleinen Fehler. Bei der Systeminitialisierung wurde die im ROM befind-
liche Vektortabelle ins RAM kopiert und anschließend eine Bank-
vertauschung durchgeführt. Kurz danach wurde auf Grund eines nicht
initialisierten Pointers der Wert 0 an Adresse 0  geschrieben. Diesen
Fehler korrigierte ich und trat dabei eine Lawine los.

Plötzlich funktionierten etliche andere Teile der Software nicht mehr.

Wie sich nämlich herausgestellt hatte, gab es in dem Projekt mindestens
zwei andere Entwickler, die die o.a. Zuweisungen (a = *NULL) und
entsprechende Abfragen (if (a == *NULL)) in das ganze Projekt gestreut
hatten...

MfG
Andreas Schweigstill

von Rolf Magnus (Gast)


Lesenswert?

>> Nur sinnvoll ist es halt nicht.
>
> Es sei denn, es liegt RAM an der Adresse 0 und man möchte darauf
> zugreifen.

In C ist es aber nicht garantiert, daß ein Nullzeiger auch wirklich eine 
Adresse enthält, deren Bits alle 0 sind.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Hallo!

Rolf Magnus schrieb:
> In C ist es aber nicht garantiert, daß ein Nullzeiger auch wirklich eine
> Adresse enthält, deren Bits alle 0 sind.

Es ist nicht durch den Sprachstandard garantiert, aber ggf. aus der
Kombination aus Sprachstandard, Prozessorarchitektur und Compiler.
Sofern man also keine beliebig portablen Programme schreiben muss, kann
man sich im Einzelfall aber doch darauf verlassen und muss wohl auch
nicht befürchten, dass sie der Compiler in Abhängigkeit von der
Mondphase neu entscheiden wird, wie er einen Nullzeiger darstellt.

Wenn man bei einer portablen Anwendung jedoch Annahmen bezüglich der
Implementierung macht, kann man die betreffenden Stellen ja auch per
Präprozessormakro absichern und einen Abbruch der Kompilierung bei einem
unbekannten Compiler oder Prozessor veranlassen.

MfG
Andreas Schweigstill

von Rolf Magnus (Gast)


Lesenswert?

> Wenn man bei einer portablen Anwendung jedoch Annahmen
> bezüglich der Implementierung macht, kann man die betreffenden
> Stellen ja auch per Präprozessormakro absichern und einen Abbruch
> der Kompilierung bei einem unbekannten Compiler oder Prozessor
> veranlassen.

Oder man macht daraus:
1
int i = 0;
2
void* p = (void*)i;

Das ist zwar auch keine Garantie, aber man umgeht damit zumindest die 
Sonderbehandlung von 0 im Zeigerkontext. Dann braucht man wenigstens 
nicht zu ermitteln, ob ein Nullzeiger wirklich die Adresse 0 enthält.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
>
1
> int i = 0;
2
> void* p = (void*)i;
3
>
>
> Das ist zwar auch keine Garantie, aber man umgeht damit zumindest die
> Sonderbehandlung von 0 im Zeigerkontext. Dann braucht man wenigstens
> nicht zu ermitteln, ob ein Nullzeiger wirklich die Adresse 0 enthält.

Das ist aber wiederum gefährlich, wenn man an anderer Stelle z.B.

if (p) {
 ...
}

if (!p) {
 ...
}

if (p == NULL) {
 ...
}

verwendet. Dort wird nämlich auf die Nullzeiger-Eigenschaft überprüft
und nicht zwingend auf die Nullwert-Eigenschaft des in einen Integer
konvertierten Zeigers.

Und es dürfte in typischen Programmen deutlich mehr Stellen geben, an
denen eine Abfrage erfolgt als die explizite Zuweisung des
Nullzeigers.

Gruß
Andreas Schweigstill

von Rolf Magnus (Gast)


Lesenswert?

> Dort wird nämlich auf die Nullzeiger-Eigenschaft überprüft
> und nicht zwingend auf die Nullwert-Eigenschaft des in einen Integer
> konvertierten Zeigers.

Wenn man einen Nullzeiger will, sollte man natürlich auch einen 
verwenden. Meine Aussage bezog sich auf den  Fall, daß man explizit 
einen Zeiger will, der die Adresse 0 enthält, z.B. weil man auf das 
zugreifen möchte, was da liegt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.