Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Adressenmanipulation

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
16.05.2012, 23:38 Uhr
banshee



Hallo,

welche "Einheit" haben eigentlich Speicheradressen in C++? Dieser Hex-Wert was bedeutet der genau? Sind das Bytes oder eine andere Einheit? Ich habe mich darüber gewundert, weil ich ein Vektor-Template gesehen habe, das folgendes Schmuckstück beinhaltet hat:


C++:
const T operator[] (unsigned int i) const {
    return *(&x+i);
  }


Mal abgesehen davon, dass man ungeschützt auf den Speicher zugreifen kann, frage ich mich, ob die nächste Variable immer an der Adresse &x+i liegt. Wenn der Typ sehr groß ist und mehr Speicher einnimmt, stimmt die Adressierung doch nicht mehr oder doch?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
17.05.2012, 09:18 Uhr
Tommix



Hallo,
nein, das ist korrekt. Du kannst ja mit z.B.

C++:
int *p = ...
p++ oder p += 1;


durch ein Array iterieren, ohne Dir über den Speicherbedarf eines int (oder was auch immer) Gedanken zu machen.
Die "Einheit" ist also sizeof<T>.

Gruß,
Tommix

Dieser Post wurde am 17.05.2012 um 09:18 Uhr von Tommix editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
17.05.2012, 12:40 Uhr
banshee



Was? Wenn ich mir eine Adresse zurückgeben lasse, dann führt der Compiler intern irgendwie die Typgröße mit und macht alle Manipulationen in dieser Einheit?! D.h. &x+i erhöht einen int um 4 Byte und einen double um 8 Byte?!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
17.05.2012, 15:54 Uhr
0xdeadbeef
Gott
(Operator)


Sofern sizeof(int) == 4 und sizeof(double) == 8, ja.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
17.05.2012, 20:43 Uhr
banshee



Wow, das war mir neu. Kann es dabei nicht zu Problemen wegen der Fragmentierung kommen? Der Compiler legt doch doubles immer an Adressen ab, die durch sizeof(double) teilbar sind, damit sie leichter adressiert werden können. Wenn man jetzt erst einen int an eine nicht durch sizeof(double) teilbare Adresse legt und dieser dann einen double zuweist, was passiert dann?
Oder kann es nicht sogar sein, dass man an die Adresse des ints einen größeren Typen packen will, der aber in das Speicherloch nicht mehr rein passt (der int aber schon), weil dahinter noch Daten sind ?
Und was passiert, wenn typlose Daten oder uninitialisierter Müll an der Adresse steht?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
17.05.2012, 21:06 Uhr
0xdeadbeef
Gott
(Operator)


Na, Moment. Zunächst mal legt der Compiler doubles nicht notwendigerweise mit einem Alignment von sizeof(double) an; MSVC für Win32 beispielsweise richtet (wenn man ihn nicht zwingt) alles auf höchstens 4 Byte aus. Prinzipiell kann ein x86- bzw. x86-64-Prozessor Maschinenworte von beliebigen Stellen aus dem Speicher ziehen (Alignment optional), erst bei SSE-Anweisungen ist eine genaue Ausrichtung erforderlich. Das ist übrigens durchaus nicht bei allen CPU-Typen so; insbesondere RISC-Architekturen erwarten in der Regel generell passend ausgerichtete Daten.

"Passend" bedeutet hier "für eine bestimmte Prozessoranweisung passend"; der Prozessor selbst weiß nicht, dass die Daten an einer bestimmten Speicherstelle etwas bezeichnen, was in einem Quellcode mal "int x" hieß, und es wäre ihm auch egal - du kannst locker auf das zweite Byte eines ints zugehen und den Speicher danach als String interpretieren, wenn du lustig bist, oder die zwei Maschinenworte eines doubles einzeln betrachten (Fließkommabibliotheken machen das dauernd). Wenn du eine Prozessoranweisung auf eine unpassende Speicherstelle los lässt, kriegst du halt einen Alignment Fault.

Was die Zeigerarithmetik angeht, so ist es normalerweise nicht hilfreich, sich in einem Array um halbe Einträge vorwärts bewegen zu können (notfalls geht das mit einem Cast nach char* aber immer noch). Die Abstraktion wird bei den unterstützten Operationen auch nicht verletzt - so ist (foo + 1) - foo == 1, auch wenn sizeof(*foo) > 1. Gerechnet wird da generell in Blöcken, nicht in Byte, und so lange du strict aliasing nicht verletzt, ist die Tatsache, dass ein Zeiger anderen Typs auf die gleiche Speicherstelle um 1 erhöht auf eine andere Stelle als foo + 1 zeigt, nicht weiter von Bedeutung.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
18.05.2012, 09:19 Uhr
ao

(Operator)



Zitat von banshee:
frage ich mich, ob die nächste Variable immer an der Adresse &x+i liegt. Wenn der Typ sehr groß ist und mehr Speicher einnimmt, stimmt die Adressierung doch nicht mehr oder doch?

Doch. Es ist eine der Grundregeln in C und C++, dass Array-Elemente direkt aneinander grenzen und dass mit *(p+i) auf das i-te Element zugegriffen werden kann. Der Compiler verspricht, die Elemente so im Speicher anzuordnen, dass das geht.

Wenn der Compiler Padding verwendet, um auf die nächste Wortgrenze zu kommen (bei Arrays von Strukturen kommt das häufiger vor), berücksichtigt er das in seiner Zeigerarithmetik und zählt die Padding-Bytes mit.


Zitat:
Mal abgesehen davon, dass man ungeschützt auf den Speicher zugreifen kann,

Was meinst du damit? Wenn man zuvor das Vektor-Template benutzt hat, um den Speicher anzulegen, dann kann man davon ausgehen, dass alles in Ordnung ist. Andernfalls hat das Template einen Bug.

Und wenn man mit einem Index kommt, der zu groß ist und hinter das Vektor-Ende greift: Das darf immer krachend abstürzen, es sei denn, das Vektor-Template behauptet, Schutz davor zu bieten. In dem Fall müsste der Index vor der Verwendung geprüft werden, und Debug-Versionen (#ifdef _DEBUG oder so) machen das häufig auch - auf Kosten der Performance.

Dieser Post wurde am 18.05.2012 um 10:57 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
18.05.2012, 12:59 Uhr
banshee




Zitat von ao:
Das darf immer krachend abstürzen, es sei denn, das Vektor-Template behauptet, Schutz davor zu bieten.


Tut es aber doch nicht. Wenn ich einen 3D-Vektor definiere und auf das 4. Element zugreife, kriege ich das zurück, was hinter dem Vektor im Speicher steht. Ich dachte, das ist aus Sicherheitsgründen immer extrem schlecht?!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
18.05.2012, 13:32 Uhr
0xdeadbeef
Gott
(Operator)


3D != der Länge 3.

Allerdings ist das schon richtig - wenn du drei Elemente anforderst, darfst du nicht das vierte verlangen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
18.05.2012, 15:03 Uhr
ao

(Operator)



Zitat von banshee:

Zitat:
Das darf immer krachend abstürzen, es sei denn, das Vektor-Template behauptet, Schutz davor zu bieten.


Tut es aber doch nicht. Wenn ich einen 3D-Vektor definiere und auf das 4. Element zugreife, kriege ich das zurück, was hinter dem Vektor im Speicher steht.


Dass du das machen kannst, heißt nicht, dass du es machen darfst. Das 4. Element existiert nicht, du greifst auf Speicher zu, der dir nicht gehört und der vielleicht vom Programm oder von der Speicherverwaltung oder von sonstwem für andere Dinge verwendet wird.

Im günstigen Fall bekommst du sofort eins auf die Finger (Access Violation), im ungünstigen Fall läuft das Programm erst mal eine Weile weiter und kracht später an ganz anderer Stelle.

Das sind äußerst fiese Fehler, die entscheidend zu dem schlechten Ruf beigetragen haben, den C und C++ in manchen Kreisen haben, und Programmierer tun gut daran, sich frühzeitig dafür zu sensibilisieren.

Dieser Post wurde am 18.05.2012 um 15:03 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: