 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Moritz Ulrich Guest
|
Posted: Fri Apr 06, 2007 1:28 am Post subject: Heap-Verständnisfrage |
|
|
Ich habe da mal eine kleine Frage zu Instanzen einer Klasse auf dem Heap.
Ein Beispiel wird wohl das passenste sein, von daher:
class foo
{
public:
foo():
~foo()
private:
int m_irgendwas[30][20];
};
Ich lasse die Implentierungen mal weg, aber nun zu meiner Frage:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle, liegt dann das Mehrdimensionale Array auch auf dem
Heap?
Gruß
Moritz |
|
| Back to top |
|
 |
Florian Weimer Guest
|
Posted: Fri Apr 06, 2007 3:55 pm Post subject: Re: Heap-Verständnisfrage |
|
|
* Moritz Ulrich:
| Quote: | Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle, liegt dann das Mehrdimensionale Array auch auf
dem Heap?
|
Die erste ebene von Pointern liegt auf dem Heap und ist
uninitialisiert. Typischerweise mußt Du die zweite Ebene von Hand
füllen, wodurch die entsprechenden Objekte ebenfalls auf dem Heap
landen. |
|
| Back to top |
|
 |
Torsten Robitzki Guest
|
Posted: Fri Apr 06, 2007 4:18 pm Post subject: Re: Heap-Verständnisfrage |
|
|
Moritz Ulrich wrote:
| Quote: | Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle, liegt dann das Mehrdimensionale Array auch auf
dem Heap?
|
Kurze Antwort: Ja. Lange Antwort: Es gibt in C++ gar keinen Heap, es
gibt eine free store.
mfg Torsten |
|
| Back to top |
|
 |
Marcel Müller Guest
|
Posted: Fri Apr 06, 2007 4:32 pm Post subject: Re: Heap-Verständnisfrage |
|
|
Moritz Ulrich wrote:
| Quote: | Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle, liegt dann das Mehrdimensionale Array auch auf
dem Heap?
|
Ja.
Alle Attribute von Klassen/Strukturen und ihren Basisklassen liegen
immer in einem Speicherblock.
Heap-Objekte können eigentlich nicht sinnvoll referenzierte Komponenten
auf dem Stack haben, da das üblicherweise Probleme mit der Lebensdauer
gibt. Andersherum geht natürlich schon.
Es gibt aber auch Ausnahmen von der Regel, z.B. für Semaphoren, die z.B.
eine Liste von wartenden Threads über Objekte auf dem Stack halten.
Marcel |
|
| Back to top |
|
 |
Moritz Ulrich Guest
|
Posted: Fri Apr 06, 2007 5:59 pm Post subject: Re: Heap-Verständnisfrage |
|
|
Am 05.04.2007, 22:28 Uhr, schrieb Moritz Ulrich
<thekenny123 (AT) googlemail (DOT) com>:
| Quote: | Ich habe da mal eine kleine Frage zu Instanzen einer Klasse auf dem Heap.
Ein Beispiel wird wohl das passenste sein, von daher:
class foo
{
public:
foo():
~foo()
private:
int m_irgendwas[30][20];
};
Ich lasse die Implentierungen mal weg, aber nun zu meiner Frage:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle, liegt dann das Mehrdimensionale Array auch auf
dem Heap?
Gruß
Moritz
|
Ok, eigentlich ist das eine sehr dumme Frage, also antworte ich mir
selber^^
Eigentlich ist das Array die einzige Sache der Klasse, die wirklich
Speicher brauch. Die Methoden liegen selber irgendwo im Speicher, sind
aber nur irgendwelcher Bytecode. Das Array sind die einzigen wirklichen
"Daten" die verändert werden etc.
Sehe ich das richtig? |
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Fri Apr 06, 2007 7:05 pm Post subject: Re: Heap-Verständnisfrage |
|
|
"Moritz Ulrich" <thekenny123 (AT) googlemail (DOT) com> writes:
| Quote: | Ich habe da mal eine kleine Frage zu Instanzen einer Klasse auf dem
Heap.
|
"Heap" ist im Kontext von C++ (oder C) kein definierter Begriff. Du
meinst Objekte mit dynamischer Lebensdauer ("storage duration"). Wo
eine C++-Implementation die anlegt, ist ihre Sache, solange sie sich
an gewisse Vorgaben hält.
| Quote: | Ein Beispiel wird wohl das passenste sein, von daher:
class foo
{
public:
foo():
~foo()
private:
int m_irgendwas[30][20];
};
Ich lasse die Implentierungen mal weg, aber nun zu meiner Frage:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle,
|
Tust Du nicht. Du erzeugst dynamisch *eine Instanz* der Klasse.
| Quote: | liegt dann das Mehrdimensionale Array auch auf dem Heap?
|
Eben, das ist implementationsabhängig.
Du darfst aber davon ausgehen, dass der Speicherbereich, den
*irgendwas belegt, zusammenhängt, die Grösse 20*30*sizeof(int) (plus
evtl. ein paar zerquetschte) hat und das Array m_irgendwas beinhaltet. |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Sat Apr 07, 2007 5:45 pm Post subject: Re: Heap-Verständnisfrage |
|
|
Torsten Robitzki wrote:
| Quote: | Moritz Ulrich wrote:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle, liegt dann das Mehrdimensionale Array auch auf
dem Heap?
Kurze Antwort: Ja. Lange Antwort: Es gibt in C++ gar keinen Heap, es
gibt eine free store.
|
Doch, gibt's schon, ist aber was ganz anderes. |
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Tue Apr 10, 2007 1:01 pm Post subject: Re: Heap-Verständnisfrage |
|
|
Thomas Maeder wrote:
| Quote: | "Moritz Ulrich" <thekenny123 (AT) googlemail (DOT) com> writes:
Ich habe da mal eine kleine Frage zu Instanzen einer Klasse auf dem
Heap.
"Heap" ist im Kontext von C++ (oder C) kein definierter Begriff. Du
meinst Objekte mit dynamischer Lebensdauer ("storage duration"). Wo
eine C++-Implementation die anlegt, ist ihre Sache, solange sie sich
an gewisse Vorgaben hält.
|
Genau.
| Quote: |
Ein Beispiel wird wohl das passenste sein, von daher:
class foo
{
public:
foo():
~foo()
private:
int m_irgendwas[30][20];
};
Ich lasse die Implentierungen mal weg, aber nun zu meiner Frage:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle,
Tust Du nicht. Du erzeugst dynamisch *eine Instanz* der Klasse.
liegt dann das Mehrdimensionale Array auch auf dem Heap?
Eben, das ist implementationsabhängig.
Du darfst aber davon ausgehen, dass der Speicherbereich, den
*irgendwas belegt, zusammenhängt, die Grösse 20*30*sizeof(int) (plus
evtl. ein paar zerquetschte) hat und das Array m_irgendwas beinhaltet.
|
Ich habe zwar jetzt eine längere C++ - Pause hinter mir, aber meine
Erinnerung sagt mir:
Nein. foo ist nicht POD, also muss der Specherbereich nicht
zusammenhängen. Der Rest des Satzes ist wohl wortauslegungssache ,
wenn Du mit Grösse den Wert des sizeof() - Operators meinst sage ich
ebenfalls nein - der bezieht sich auf die object-representation des
Objektes (zum Unterschied zur value-representation - und wie die dann
implementiert ist schreibt sowieso niemand vor).
Es ist legal, die klasse foo als Implementation nur mit einem Zeiger auf
z.b. das array auszustatten, dass dann irgendwo liegen kann. Dann wäre
sizeof(foo) == sizeof(internerPointer) |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Wed Apr 11, 2007 10:13 am Post subject: Re: Heap-Verständnisfrage |
|
|
Thomas Mang wrote:
| Quote: | Thomas Maeder wrote:
"Moritz Ulrich" <thekenny123 (AT) googlemail (DOT) com> writes:
Ich habe da mal eine kleine Frage zu Instanzen einer Klasse auf dem
Heap.
"Heap" ist im Kontext von C++ (oder C) kein definierter Begriff.
|
Doch, er ist definiert, aber anders. Aus der C++-Norm:
"A heap is a particular organization of elements in a range between two
random access iterators [a, b).
Its two key properties are:
(1) *a is the largest element in the range and
(2) *a may be removed by pop_heap(), or a new element added by push_heap(),
in O(log N) time."
| Quote: | Ein Beispiel wird wohl das passenste sein, von daher:
class foo
{
public:
foo():
~foo()
private:
int m_irgendwas[30][20];
};
Ich lasse die Implentierungen mal weg, aber nun zu meiner Frage:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle,
Tust Du nicht. Du erzeugst dynamisch *eine Instanz* der Klasse.
liegt dann das Mehrdimensionale Array auch auf dem Heap?
Eben, das ist implementationsabhängig.
Du darfst aber davon ausgehen, dass der Speicherbereich, den
*irgendwas belegt, zusammenhängt, die Grösse 20*30*sizeof(int) (plus
evtl. ein paar zerquetschte) hat und das Array m_irgendwas beinhaltet.
Ich habe zwar jetzt eine längere C++ - Pause hinter mir, aber meine
Erinnerung sagt mir:
Nein. foo ist nicht POD, also muss der Specherbereich nicht
zusammenhängen. Der Rest des Satzes ist wohl wortauslegungssache ,
wenn Du mit Grösse den Wert des sizeof() - Operators meinst sage ich
ebenfalls nein - der bezieht sich auf die object-representation des
Objektes (zum Unterschied zur value-representation - und wie die dann
implementiert ist schreibt sowieso niemand vor).
|
Zu den Begriffen meint die C++-Norm:
"The object representation of an object of type T is the sequence of N
unsigned char objects taken up by the object of type T, where N equals
sizeof(T). The value representation of an object is the set of bits
that hold the value of type T."
Das scheint zu bedeuten, daß mit "object representation" der Speicher
gemeint ist, den das Objekt belegt, während die "value representation"
einfach die Daten sind, die dann in diesem Speicher liegen.
| Quote: | Es ist legal, die klasse foo als Implementation nur mit einem Zeiger auf
z.b. das array auszustatten, dass dann irgendwo liegen kann.
|
Kannst du das irgendwie belegen? |
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Wed Apr 11, 2007 8:28 pm Post subject: Re: Heap-Verständnisfrage |
|
|
On Apr 10, 10:01 am, Thomas Mang <noth...@provided.com> wrote:
| Quote: | Thomas Maeder wrote:
"Moritz Ulrich" <thekenny...@googlemail.com> writes:
[...]
Ein Beispiel wird wohl das passenste sein, von daher:
class foo
{
public:
foo():
~foo()
private:
int m_irgendwas[30][20];
};
Ich lasse die Implentierungen mal weg, aber nun zu meiner Frage:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle,
Tust Du nicht. Du erzeugst dynamisch *eine Instanz* der Klasse.
liegt dann das Mehrdimensionale Array auch auf dem Heap?
Eben, das ist implementationsabhängig.
Du darfst aber davon ausgehen, dass der Speicherbereich, den
*irgendwas belegt, zusammenhängt, die Grösse 20*30*sizeof(int) (plus
evtl. ein paar zerquetschte) hat und das Array m_irgendwas beinhaltet.
Ich habe zwar jetzt eine längere C++ - Pause hinter mir, aber meine
Erinnerung sagt mir:
Nein. foo ist nicht POD, also muss der Specherbereich nicht
zusammenhängen.
|
Jein. Es kann in Prinzip vorkommen, dass es löcher drin gibt,
aber... sizeof(foo) muss eine Konstante sein, und es muss bei
new foo genau einen Aufruf operator new geben, mit als Parameter
sizeof(foo). Damit sind die Möglichkeiten etwas begrenzt.
Zeigerarithmetik muss auch funktionnieren, wenn man einen Feld
von foo hat; ich glaube sogar, dass angegeben foo* p, (char*)p
<= (char*)p->m_irgendwas < (char*)(p + 1) garantiert ist. (Ich
bin aber nicht sicher darüber.)
| Quote: | Der Rest des Satzes ist wohl wortauslegungssache ,
wenn Du mit Grösse den Wert des sizeof() - Operators meinst sage ich
ebenfalls nein - der bezieht sich auf die object-representation des
Objektes (zum Unterschied zur value-representation - und wie die dann
implementiert ist schreibt sowieso niemand vor).
Es ist legal, die klasse foo als Implementation nur mit einem Zeiger auf
z.b. das array auszustatten, dass dann irgendwo liegen kann. Dann wäre
sizeof(foo) == sizeof(internerPointer)
|
Ich glaube nicht. Gehen wir davon aus, dass ich operator new
ersetzt habe. Damit sind Aufrufe von ihm "sichtbares Verhalten".
Also: wenn man "new foo" schreibt, muss operator new genau
einmal aufgerufen werden, weder mehr noch weniger. Angegeben, er
ermittelt einen Zeiger zurück; nachdem darf keine Ausnahme
auftreten, es sei dann, ich habe es im Constructor explizit
geschrieben. Woher dann soll anderer Speicher kommen?
--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Thu Apr 12, 2007 4:06 am Post subject: Re: Heap-Verständnisfrage |
|
|
Rolf Magnus wrote:
| Quote: | Thomas Mang wrote:
Ein Beispiel wird wohl das passenste sein, von daher:
class foo
{
public:
foo():
~foo()
private:
int m_irgendwas[30][20];
};
Ich lasse die Implentierungen mal weg, aber nun zu meiner Frage:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle,
Tust Du nicht. Du erzeugst dynamisch *eine Instanz* der Klasse.
liegt dann das Mehrdimensionale Array auch auf dem Heap?
Eben, das ist implementationsabhängig.
Du darfst aber davon ausgehen, dass der Speicherbereich, den
*irgendwas belegt, zusammenhängt, die Grösse 20*30*sizeof(int) (plus
evtl. ein paar zerquetschte) hat und das Array m_irgendwas beinhaltet.
Ich habe zwar jetzt eine längere C++ - Pause hinter mir, aber meine
Erinnerung sagt mir:
Nein. foo ist nicht POD, also muss der Specherbereich nicht
zusammenhängen. Der Rest des Satzes ist wohl wortauslegungssache ,
wenn Du mit Grösse den Wert des sizeof() - Operators meinst sage ich
ebenfalls nein - der bezieht sich auf die object-representation des
Objektes (zum Unterschied zur value-representation - und wie die dann
implementiert ist schreibt sowieso niemand vor).
Zu den Begriffen meint die C++-Norm:
"The object representation of an object of type T is the sequence of N
unsigned char objects taken up by the object of type T, where N equals
sizeof(T). The value representation of an object is the set of bits
that hold the value of type T."
Das scheint zu bedeuten, daß mit "object representation" der Speicher
gemeint ist, den das Objekt belegt, während die "value representation"
einfach die Daten sind, die dann in diesem Speicher liegen.
|
Das magische Wort in Deinem Satz lautet "in *diesem* Speicher liegen".
Für PODs lese ich die Norm so dass das gegeben sein muss (3.9/4 nächster
Satz):
"For POD types, the value representation is a set of bits in the object
representation that determines a value, which is one discrete element of
an implementation-defined set of values."
Für nicht-POD steht nichts entsprechendes da.
| Quote: |
Es ist legal, die klasse foo als Implementation nur mit einem Zeiger auf
z.b. das array auszustatten, dass dann irgendwo liegen kann.
Kannst du das irgendwie belegen?
|
Meiner Meinung nach musst Du das Gegenteil belegen, nämlich dass die
value-representation immer in der object-representation liegen muss. Ich
kenne keinen Paragraphen der dies verlangt, deshalb ist mein
Umkehrschluss eben dass es nicht so sein muss.
Praktisch gesehen ... unterschreibe ich mit gutem Gewissen dass es so
sein wird. Ich glaube aber nicht dass es explizit verlangt wird.
Thomas |
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Thu Apr 12, 2007 4:48 am Post subject: Re: Heap-Verständnisfrage |
|
|
James Kanze wrote:
| Quote: | On Apr 10, 10:01 am, Thomas Mang <noth...@provided.com> wrote:
Thomas Maeder wrote:
"Moritz Ulrich" <thekenny...@googlemail.com> writes:
[...]
Ein Beispiel wird wohl das passenste sein, von daher:
class foo
{
public:
foo():
~foo()
private:
int m_irgendwas[30][20];
};
Ich lasse die Implentierungen mal weg, aber nun zu meiner Frage:
Wenn ich diese Klasse z.b. mit
foo *irgendwas = new foo();
auf dem Heap erstelle,
Tust Du nicht. Du erzeugst dynamisch *eine Instanz* der Klasse.
liegt dann das Mehrdimensionale Array auch auf dem Heap?
Eben, das ist implementationsabhängig.
Du darfst aber davon ausgehen, dass der Speicherbereich, den
*irgendwas belegt, zusammenhängt, die Grösse 20*30*sizeof(int) (plus
evtl. ein paar zerquetschte) hat und das Array m_irgendwas beinhaltet.
Ich habe zwar jetzt eine längere C++ - Pause hinter mir, aber meine
Erinnerung sagt mir:
Nein. foo ist nicht POD, also muss der Specherbereich nicht
zusammenhängen.
Jein. Es kann in Prinzip vorkommen, dass es löcher drin gibt,
aber... sizeof(foo) muss eine Konstante sein, und es muss bei
new foo genau einen Aufruf operator new geben, mit als Parameter
sizeof(foo). Damit sind die Möglichkeiten etwas begrenzt.
Zeigerarithmetik muss auch funktionnieren, wenn man einen Feld
von foo hat; ich glaube sogar, dass angegeben foo* p, (char*)p
= (char*)p->m_irgendwas < (char*)(p + 1) garantiert ist. (Ich
bin aber nicht sicher darüber.)
|
Im ersten Teil stimme ich mit Dir überein. Was den Zeigervergleich
angeht bin ich allgemein auch ziemlich unsicher (ich kann den
Paragraphen mit den Garantien für Speicheraddressen im Moment überhaupt
nicht finden).
| Quote: |
Der Rest des Satzes ist wohl wortauslegungssache ,
wenn Du mit Grösse den Wert des sizeof() - Operators meinst sage ich
ebenfalls nein - der bezieht sich auf die object-representation des
Objektes (zum Unterschied zur value-representation - und wie die dann
implementiert ist schreibt sowieso niemand vor).
Es ist legal, die klasse foo als Implementation nur mit einem Zeiger auf
z.b. das array auszustatten, dass dann irgendwo liegen kann. Dann wäre
sizeof(foo) == sizeof(internerPointer)
Ich glaube nicht. Gehen wir davon aus, dass ich operator new
ersetzt habe. Damit sind Aufrufe von ihm "sichtbares Verhalten".
Also: wenn man "new foo" schreibt, muss operator new genau
einmal aufgerufen werden, weder mehr noch weniger. Angegeben, er
ermittelt einen Zeiger zurück; nachdem darf keine Ausnahme
auftreten, es sei dann, ich habe es im Constructor explizit
geschrieben. Woher dann soll anderer Speicher kommen?
|
Das ist das Problem des Compilers
Nein, im Ernst, praktisch gesehen ist das selbstverständlich ein sehr
sehr guter Grund (nebst anderen) dass die value-representation immer ein
Teil der object representation ist. Nur glaube ich nicht dass es
verpflichtet ist - auch nicht implizit über Umwege.
Rein theoretisch ist es ja möglich dass im gesamten Programm nur eine
z.B. Handvoll foo-s per new-expression erzeugt werden, und der Compiler
dass weiß. Wenn er garantieren kann dass für jede Instanz genug Speicher
für das array irgendwo zur Verfügung steht (z.B. im selben
Speicherbereich wo static - objects angelegt werden), sollte ja alles in
Ordnung sein. Genauso wäre es möglich, dass er das object-layout von foo
abhängig davon macht ob operator new überschrieben wurde oder nicht.
Selbstverständlich sind das alles Dinge die ich von keinem realen
Compiler erwarte (das hätte ich vielleicht von Anfang an klarer
schreiben sollen). Aber sind sie deshalb per se ausgeschlossen?
Ich kann mich an eine heiße Diskussion über object-layout und ähnliches
erinnern:
http://groups.google.com/group/comp.lang.c++.moderated/tree/browse_frm/thread/4a0661ad428ab619/
Da ging es teilweise zwar um contiguous und nicht-contiguous objects,
aber vielleicht ist ja was besonders nützliches dabei.
Thomas |
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Fri Apr 13, 2007 12:51 am Post subject: Re: Heap-Verständnisfrage |
|
|
Thomas Mang wrote:
Es war wirklich in dieser Diskussion, aber wegen der Länge letzter
ziemlich gut versteckt:
Die Idee mit dem Zeiger statt Datenmember wird von David Abrahams hier
aufgeworfen:
http://tinyurl.com/28djes
und die Antwort wegen exception kommt hier:
http://tinyurl.com/yuoknz
Also greift wieder mal die
"jedes-Programm-ist-Undef.-Verhalten-weil-wenn-es-sonst-nichts-ist-dann-sind-eben-ressourcen-limiert"
Regel.
Zu diesen Punkten ist dann kein weiterer Widerspruck hinzugekommen.
Dazwischen eist auch ein netter, langer Exkurs über contiguous, region,
subojects, Englisch-Lesen etc. Und dass man die Norm stets im Sinne der
Erfinder lesen muss, auch wenn die sich vielleicht nicht so klar
ausgedrückt haben...
Nach all dem sage ich:
Für jeden non-POD-typ darf man weder damit rechnen, dass die
Objekt-repräsentation in einem zusammenhängenden Stück Speicher liegt,
noch dass sizeof(someClass) mindestens die Summe von sizeof aller
Daten-member ist - wenngleich diese value-bits selbstverständlich
irgendwo liegen müssen [es sei denn sie werden aufgrund von as-if gar
nicht gebraucht...]
Thomas |
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Fri Apr 13, 2007 6:35 pm Post subject: Re: Heap-Verständnisfrage |
|
|
On Apr 12, 1:48 am, Thomas Mang <noth...@provided.com> wrote:
| Quote: | James Kanze wrote:
On Apr 10, 10:01 am, Thomas Mang <noth...@provided.com> wrote:
Thomas Maeder wrote:
Jein. Es kann in Prinzip vorkommen, dass es löcher drin gibt,
aber... sizeof(foo) muss eine Konstante sein, und es muss bei
new foo genau einen Aufruf operator new geben, mit als Parameter
sizeof(foo). Damit sind die Möglichkeiten etwas begrenzt.
Zeigerarithmetik muss auch funktionnieren, wenn man einen Feld
von foo hat; ich glaube sogar, dass angegeben foo* p, (char*)p
= (char*)p->m_irgendwas < (char*)(p + 1) garantiert ist. (Ich
bin aber nicht sicher darüber.)
Im ersten Teil stimme ich mit Dir überein. Was den Zeigervergleich
angeht bin ich allgemein auch ziemlich unsicher (ich kann den
Paragraphen mit den Garantien für Speicheraddressen im Moment überhaupt
nicht finden).
|
Ich auch nicht:-). Ich denke aber, dass es der Absicht
entspricht.
Wobei es geht nur um Adressen, die du als Programmierer erhalten
kannst. Mann kann z.B. die vtable als Bestandteil des Objektes
betrachten; immerhin wird sie sicher nicht zwischen den Anfangs-
und Endeadressen liegen. (Siehe aber unten.)
| Quote: | Der Rest des Satzes ist wohl wortauslegungssache ,
wenn Du mit Grösse den Wert des sizeof() - Operators meinst sage ich
ebenfalls nein - der bezieht sich auf die object-representation des
Objektes (zum Unterschied zur value-representation - und wie die dann
implementiert ist schreibt sowieso niemand vor).
Es ist legal, die klasse foo als Implementation nur mit einem Zeiger auf
z.b. das array auszustatten, dass dann irgendwo liegen kann. Dann wäre
sizeof(foo) == sizeof(internerPointer)
Ich glaube nicht. Gehen wir davon aus, dass ich operator new
ersetzt habe. Damit sind Aufrufe von ihm "sichtbares Verhalten".
Also: wenn man "new foo" schreibt, muss operator new genau
einmal aufgerufen werden, weder mehr noch weniger. Angegeben, er
ermittelt einen Zeiger zurück; nachdem darf keine Ausnahme
auftreten, es sei dann, ich habe es im Constructor explizit
geschrieben. Woher dann soll anderer Speicher kommen?
Das ist das Problem des Compilers
Nein, im Ernst, praktisch gesehen ist das selbstverständlich ein sehr
sehr guter Grund (nebst anderen) dass die value-representation immer ein
Teil der object representation ist. Nur glaube ich nicht dass es
verpflichtet ist - auch nicht implizit über Umwege.
|
In der Tat ist das Problem des Compilers. Dazu hat der Compiler
immer eine Ausrede: obwohl ich es nicht in der C++-Norm finde,
in C ist es undefiniertes Verhalten, wenn man die
Ressource-Limiten des Systems überschritt. (Nötige Beschränkung,
eigenlich, weil die abstrakte Maschine unendlich ist.) Also,
z.B. will der Compiler Bounds-Checking implementieren. Er kann
dann sagen, dass es eine höchste Anzahl von Zeigern, une einen
Feld mit Descriptoren von Zeigern mit dieser Grösse statisch
anlegen. Dann erfolgt es tatsächlich, dass ein Teil der
Darstellung eines Zeigers anderswo liegt. Nur denke ich, dass es
auch dem Programm transparent sein muss, solange das Programm
nichts unerlaubt (undefiniertes Verhalten) macht, und innerhalb
den Grenzen deiser Ressource-Limite bleibt.
--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Fri Apr 13, 2007 10:29 pm Post subject: Re: Heap-Verständnisfrage |
|
|
James Kanze wrote:
| Quote: | On Apr 12, 1:48 am, Thomas Mang <noth...@provided.com> wrote:
James Kanze wrote:
On Apr 10, 10:01 am, Thomas Mang <noth...@provided.com> wrote:
Thomas Maeder wrote:
Jein. Es kann in Prinzip vorkommen, dass es löcher drin gibt,
aber... sizeof(foo) muss eine Konstante sein, und es muss bei
new foo genau einen Aufruf operator new geben, mit als Parameter
sizeof(foo). Damit sind die Möglichkeiten etwas begrenzt.
Zeigerarithmetik muss auch funktionnieren, wenn man einen Feld
von foo hat; ich glaube sogar, dass angegeben foo* p, (char*)p
= (char*)p->m_irgendwas < (char*)(p + 1) garantiert ist. (Ich
bin aber nicht sicher darüber.)
Im ersten Teil stimme ich mit Dir überein. Was den Zeigervergleich
angeht bin ich allgemein auch ziemlich unsicher (ich kann den
Paragraphen mit den Garantien für Speicheraddressen im Moment überhaupt
nicht finden).
Ich auch nicht:-). Ich denke aber, dass es der Absicht
entspricht.
|
Ich glaube eher nicht, dass es Absicht war.
In 5.9/2 steht einiges über Garantien für Vergleich von Zeigern auf
Datenmembern. Ich weiß aber nicht inwiefern das dort alles im
Zusammenhang mit der char* - Konvertierung in Deinem Beispiel zu lesen
ist - gelten die konvertierten char* Zeiger noch als zeiger auf
Datenmember (die Datenmember sind ja nicht char)?
Ausserdem, nehmen wir abgeleitete Klassen hinzu. Das object-layout
zwischen Basisklasse und abgeleiteter Klasse ist explizit unspezifiziert
(10.1/3). Dazu kommt noch, dass object-layouts nicht einmal stets ident
sein müssen (10.1/5 - wahrscheinlich primär wegen empty base classes).
Ich glaube es ist klar dass bei:
struct base
{
base() {}
};
struct derived : base
{};
es keine Garantie gibt dass der Teil der abgeleiteten Klasse "hinter"
(also höhere Adresse) der Basisklasse kommt. Hat man ein Objekt D vom
Typ derived, so ist folgendes keinesfalls garantiert:
&static_cast<base>(D) < &D
Wenn wir jetzt einen 'normalen' Compiler nehmen der value-bits stets als
Teil der object-bits implementiert, dann gibt es bei abgeleiteten
Klassen logischerweise keine Garantie dass Daten-member (aus einer
Basisklasse) eine höhere Adresse haben als der this-pointer.
Die einzige echte Garantie die ich kenne ist 9.2/12. Und wie Du treffend
erwähnt hast, Adressen im Zeigersinn müssen ja nicht notwendigerweise
den tatsächlichen Adressen im Speichersystem entsprechen - weder vom
absoluten Wert her, noch bei Vergleichsoperationen mit Zeigern, also was
5.9 / 5.10 garantieren.
Ich kann mir sogar Fälle vorstellen wo ein Compiler mit bestem Gewissen
und mit positivem Resultat Datenmember aus der Objektrepräsentation
auslagert:
Nimm eine Klasse, die relativ groß ist (im Sinne von bytes für die
value-representation), wovon auf die kleinen Datenmember ständig
zugegriffen wird, auf ein paar große (wieder im Sinne von value-bits)
jedoch nur selten (z.b. indem ständig über ein Feld iteriert wird). je
nach Systemarchitektur, cache-Größen und Speicherzugriffskosten kann es
dann sehr wohl Sinn ergeben die Objekte schlank zu machen und nur die
'wichtigsten, kleinen' Datenmember in der Objektrepräsentation zu
speichern, während die 'selten genutzten, grossen' woanders liegen und
im Objekt nur einen Zeiger dorthin gespeichert ist.
| Quote: |
Das ist das Problem des Compilers
Nein, im Ernst, praktisch gesehen ist das selbstverständlich ein sehr
sehr guter Grund (nebst anderen) dass die value-representation immer ein
Teil der object representation ist. Nur glaube ich nicht dass es
verpflichtet ist - auch nicht implizit über Umwege.
In der Tat ist das Problem des Compilers. Dazu hat der Compiler
immer eine Ausrede: obwohl ich es nicht in der C++-Norm finde,
in C ist es undefiniertes Verhalten, wenn man die
Ressource-Limiten des Systems überschritt. (Nötige Beschränkung,
eigenlich, weil die abstrakte Maschine unendlich ist.)
|
So weit ich weiß ist das vom C-Standard übernommen worden und noch um
Annex B erweitert worden - wobei der 1) sowieso non-normative ist, und
2) selbst das was da drinnen steht lediglich guidelines sind.
Thomas |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|