Identifizierung v. Obj anhand Ihrer Byte Struktur

Hallo,

mal angenommen, dass ich ein Pointer auf ein Objekt bekomme und ich mich aus unerfindlichen Gründen nicht darauf verlassen kann, dass der Pointer entweder gültig ist oder NULL, kann ich durch rudimentäres Tricksen herausfinden ob der mir bekanntgemachte pointer auf keinen Stuss zeigt?

Mein erster Gedanke dazu war, dass man ein Objekt bestimmt anhand der ersten Bytes die im Spoeicher hinterlegt sind identifizieren kann.

Das bedeutet aber, dass ich zumindes an dieser Adresse und an den folgenden Bytes lesenden Zugriff brauche.

Best-Case wär also, dass genau an dieser Adresse für die Anzahl an Bytes die ich zur Identifizierung brauchen würde mein Programm irgendwelche anderen Daten geschrieben hat.

Es ist aber auch möglich Daten von Objekten zu lesen die bereits freigegeben wurden ( und noch nicht überschrieben sind )
Jeder kennt das Spiel:
int * pint = NULL;
{
int iloc( 50 );
pint = &iloc;
}
cout

Hiho,

das ist ne spannende Frage. Leider gibts da keine Antwort in Deinem Sinne darauf. Wenn Du tatsächlich versuchst auf einen ungültigen Zeiger zuzugreifen, dann kann es schon Dein Programm zum Abstürzen bringen.

Wenn Du versuchen willst, durch casting auf die ‚Rohdaten‘ zugreifen kann es ja genau so passieren, dass das drin steht, was Du erwartest, die Klasse aber trozdem nicht gültig ist, da gelöscht und nur noch nicht überschrieben.

Aber ich sags mal so. Millionen Programmierer kommen auch ohne solche Tricks aus und es geht trozdem^^. Wenn Du drauf angewiesen bist, dann solltest Du Dein Programmdesign auf jeden Fall mal überdenken.

Grüße,

Hallo szmmctag

mal angenommen, dass ich ein Pointer auf ein Objekt bekomme
und ich mich aus unerfindlichen Gründen nicht darauf verlassen
kann, dass der Pointer entweder gültig ist oder NULL,

Doch, das kannst Du. Er kann nur „gültig oder NULL“ sein, aber s.u…

kann ich
durch rudimentäres Tricksen herausfinden ob der mir
bekanntgemachte pointer auf keinen Stuss zeigt?

Du kannst natürlich mit „if §“ abfragen, ob der gültig ist (stark empfohlen). Du hast es aber wohl anders gemeint, s.u…

Das bedeutet aber, dass ich zumindes an dieser Adresse und an
den folgenden Bytes lesenden Zugriff brauche.

Wenn Du mal den Zeiger hast, kannst du auch die Daten lesen (im „public scope“) - ist das ein Problem?

Best-Case wär also, dass genau an dieser Adresse für die
Anzahl an Bytes die ich zur Identifizierung brauchen würde
mein Programm irgendwelche anderen Daten geschrieben hat.

Dann schreibst Du sie halt (die richtigen) - wer hält Dich davon ab?
z.B.

struct Objekt {
 char ident[16];
 int sonstwas;
};

Das „ident[0]“ ist dann das nullte Byte an der Adresse des Objekts.

cout

int * pint = NULL;
{
int iloc( 50 );
pint = &iloc;
}
cout


martin b:
Zeiger können natürlich *veralten*, deshalb empfiehlt sich ein gesunde Gründlichkeit mit dem „if §“, s.o…

-> Das würde mir warscheinlich den Kopf kosten weil ein „if( ptr )“ entspricht einem ist die Adresse gleich 0x00000000 und das ist nur dann der Fall wenn ich den Pointer vorher auf NULL gesetzt habe. Wenn ich allerdings ein delete auf den Pointer mache dann ist die Adresse noch lange nicht NULL sondern immer noch gültig die Daten die an der Adresse lagen sind es aber nicht mehr


martin b:
struct Objekt {
char ident[16];
int sonstwas;
};
Das „ident[0]“ ist dann das nullte Byte an der Adresse des Objekts.

Schonmal sehr interessant nur wie verhällt sich das wenn mein Objekt auch einen Konstruktor hat oder Methoden die ggf. private bzw. public sind kann ich das auch sehen wenn ich mein Objekt mit folgendermaßen durchlaufe?

for( int i=0; i

Aber ich sags mal so. Millionen Programmierer kommen auch ohne
solche Tricks aus und es geht trozdem^^. Wenn Du drauf
angewiesen bist, dann solltest Du Dein Programmdesign auf
jeden Fall mal überdenken.

xD das Programmdesign ist historisch gewachsen das hat sich niemand einfach so ausgedacht. Nein… es ist entstanden innerhalb der letzten 12 Jahre, es ist so allumfassend und enthällt die genialsten Ansätze von fast einer ganzen Armee von Programmieren (Manchmal neige ich zu Übertreiben).

…Und manchmal gibt es Probleme mit dem Design die man einfach nicht zu beheben vermag :frowning:

Jedenfalls habe ich einen Pointer und er ist nicht immer gültig (Null ist er auch nicht)

martin b:
Zeiger können natürlich *veralten*, deshalb empfiehlt sich ein
gesunde Gründlichkeit mit dem „if §“, s.o…

-> Das würde mir warscheinlich den Kopf kosten weil ein „if(
ptr )“ entspricht einem ist die Adresse gleich 0x00000000

Quark mit Soosse. Wenn du „if( ptr )“ schreibst, fragst Du ab, ob der true ist, also ungleich NULL (oder Zahl 0, was macht’s). Im Falle der ungültig ist, wird das if nicht ausgeführt.

und
das ist nur dann der Fall wenn ich den Pointer vorher auf NULL
gesetzt habe. Wenn ich allerdings ein delete auf den Pointer
mache dann ist die Adresse noch lange nicht NULL sondern immer
noch gültig

Quark mit Soosse. Du schreibst ja selbst ganz richtig, dass gelöschte Zeiger zu vergessen sind. Auch hier ist es eine Frage der gesunden Gründlichkeit, den immer auch auf NULL zu setzen.

die Daten die an der Adresse lagen sind es aber
nicht mehr

Die sind dann auch zu vergessen.

martin b:
struct Objekt {
char ident[16];
int sonstwas;
};
Das „ident[0]“ ist dann das nullte Byte an der Adresse des
Objekts.

Schonmal sehr interessant nur wie verhällt sich das wenn mein
Objekt auch einen Konstruktor hat oder Methoden die ggf.
private bzw. public sind kann ich das auch sehen wenn ich mein
Objekt mit folgendermaßen durchlaufe?

for( int i=0; i

Hallo,

mal angenommen, dass ich ein Pointer auf ein Objekt bekomme
und ich mich aus unerfindlichen Gründen nicht darauf verlassen
kann, dass der Pointer entweder gültig ist oder NULL, kann ich
durch rudimentäres Tricksen herausfinden ob der mir
bekanntgemachte pointer auf keinen Stuss zeigt?
Wie wird eigentlich ein Objekt einer Klasse im Speicher
abgelegt??? kann ich da überhaupt von Klasse zu Klasse gewisse
Unterschiede erkennen oder ist ein Objekt nichts anderes wie
ein Haufen aneinander gehängerter Member-Variablen?

Hallo Stef,

ein Speicherberich ist ein Sequenz von Bits, mehr nicht.
Die Klasse wird als Maske drüber gelegt, um zu wissen,
was die Daten bedeuten.
(siehe auch http://en.wikipedia.org/wiki/Data_structure_alignment)

Eine Ausnahme ist der Zeiger auf die virtual function
table, die dann die Adressen der Member-Funktionen enthält.
Pro Klasse (nicht Object) gibt es eine Tabelle.

Lesend kann man auf einen freigegeben Speicherbereich zugreifen,
ist kein Problem.
Wenn du dann am Anfang der Klasse eine Variable definierst, die eine definierte Bitfolge enthält, die vom Destruktor dann gelöscht wird, sollte man damit erkennen können, ob der Speicher noch gültig ist. (Falls der Speicherbereich nach dem Freigeben erneut wieder benutzt wird, kann das natürlich auch schief gehen :smile:

Interessant ist evt. auch noch, sich mit dem Heapwalk zu beschäftigen,

http://msdn.microsoft.com/en-us/library/ee175819%28V…

Den Walk durchzuführen ist zu langsam, aber evt. liegen diese Heap-Infos direkt vor dem Speicherbereich, genau weiss ich das aber nicht.

Viele Grüße
Thorsten

Hallo Stef,

da fällt mir noch ein Grund ein, warum ein Zeiger != NULL auf einen freibegenen Speicherbereich zeigt:

delete p; (hier fliegt eine Exception)
p = NULL; (wird daher nicht ausgeführt)

Exception-safe programmiert sieht das dann so aus:

try
{
 delete p;
 p = NULL;
}
catch(...)
{
 p = NULL;
 throw; 
}

Alle Codestellen auf diese Weise zu refaktorieren (falls es soetwas ist), ist meinem anderen Vorschlag auf jeden Fall vorzuziehen :smile:

Oder boost::shared_ptr verwenden … http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/…

Viel Erfolg
Thorsten

Hi McGee,

delete p; (hier fliegt eine Exception)
p = NULL; (wird daher nicht ausgeführt)

sorry, aber das ist Humbug. delete und delete[] haben per Standard (ISO 14882-2003) ein throw() in ihrer Signatur. Sie dürfen also keine Exception werfen, weder für NULL Werte noch für irgendeinen Wert != 0. Würden Sie es trotzdem tun, so müsste per selbigem Standard sofort ::unexpected() und in Ermangelung einer verfügbaren Exception-Spec ohnehin sowieso ::terminate() aufgerufen werden.

Aus 3.7.3.2:
void operator delete(void\*) throw();
void operator delete[](void\*) throw();

Aus 3.7.3.2.4:
The effect of using an invalid pointer value … is undefined.
33) It might cause a system generated runtime fault (=> terminate)

Bei einem runtime-fault, bei dem das Program sowieso terminiert wird, macht es aber keinen Sinn mehr darüber nachzudenken, einen Pointer auf 0 zu setzen …

Gruss
norsemanna

Ihh,

dann ab in den garbage collector damit^^ (scnr). Schrottigen Quellcode von anderen bearbeiten, das kenne ich auch zu genüge. Das macht wenig Spaß.

Auch wenn ich zum Thema nix mehr beitragen kann, mein Mitleid hast Du.

Grüße

Hi McGee,

delete p; (hier fliegt eine Exception)
p = NULL; (wird daher nicht ausgeführt)

sorry, aber das ist Humbug.

Nee, ist kein Humbug.

delete und delete[] haben per
Standard (ISO 14882-2003) ein throw() in ihrer Signatur.

das mag sein, Theorie ist tool, aber ich habs ausprobiert:

#include "stdafx.h"
#include 


class Foo
{
public:
 Foo()
 {
 }
 ~Foo()
 {
 throw std::exception("Hallo");
 }
};

int \_tmain(int argc, \_TCHAR\* argv[])
{
 Foo \* f = new Foo();
 try
 {
 delete f;
 f = NULL;
 }
 catch(std::exception & e)
 {
 e;
 printf("Exception gefangen: f = %p\n", f);
 }

 printf("Ende\n");
}

Unter Visual Studio 2008 ist die Ausgabe:

Exception gefangen: f = 006E7110
Ende

Beste Grüße
Thorsten

hi,

wow so ein Beispiel und dann voll daneben gehauen.

Dir ist schon klar, dass die Exception nicht von delete kommt sondern von Deinem Destruktor und nur weiterereicht wird?

Grüße,

Ja,

natürlich. Das delete ruft den Konstruktor auf,
der wirft eine Exception und damit wird das p=NULL
nicht mehr ausgeführt. So wie im Anfangspost behaupted.

Was ist dein Problem? Willst Du mich beleidigen?

Grüße
Thorsten

Howdy,

Was ist dein Problem? Willst Du mich beleidigen?

Nein, hat er nicht, denn auch Destruktoren haben per C++ Definition eine throw() Signatur. Die Tatsache, dass ein paar Bekloppte in Redmont ihren Compiler/Codegenerator nicht im Griff haben, kannst du hier nicht für allgemeine Antworten verwenden. Microsoft ist nicht die Welt, auch wenn sie es selbst glauben.

Gruss
norsemanna

Huch, da muss ich mich entschuldigen. Das sollte gar nicht so hart rüberkommen^^. (sry, hab davor im wow forum gelesen ).

Das Problem jedoch an der Sache ist, wenn Dein Pointer auf einen nicht gültigen Bereich zeigt, dann wird da auch keine Exception mehr kommen und Grundsätzlich so aus dem Dtor zu gehen willst du ja auch nicht wirklich oder?

Im Grunde hab ich grad das Gefühl, wir schreiben aneinander vorbei.

Grüße,

martin b:
Zeiger können natürlich *veralten*, deshalb empfiehlt sich ein
gesunde Gründlichkeit mit dem „if §“, s.o…

-> Das würde mir warscheinlich den Kopf kosten weil ein „if(
ptr )“ entspricht einem ist die Adresse gleich 0x00000000

Quark mit Soosse. Wenn du „if( ptr )“ schreibst, fragst Du ab,
ob der true ist, also ungleich NULL (oder Zahl
0, was macht’s). Im Falle der ungültig ist, wird das if nicht
ausgeführt.

Da hast du natürlich recht, dass das eine Abfrage auf ptr==true ist. Ich habe da wohl etwas schnell geschrieben.
Hier meine ofizielle Verbesserung:

[…]ein „if( ptr )“ entspricht einem „ist die Adresse gleich ungleich 0x00000000“

Im übrigen mache ich das auch schon aber anscheinend hast du mein Problem nicht genau verstanden:

Ich habe einen Pointer der != NULL ist auf den aber schon ein delete durchgeführt, jedoch nicht auf NULL gesetzt wurde.

Meine Frage war wie ich diesen Fall erkennen kann.
Da hilft mir aber ein if(ptr) leider nicht weiter…

das ist nur dann der Fall wenn ich den Pointer vorher auf NULL
gesetzt habe. Wenn ich allerdings ein delete auf den Pointer
mache dann ist die Adresse noch lange nicht NULL sondern immer
noch gültig

Quark mit Soosse. Du schreibst ja selbst ganz richtig, dass
gelöschte Zeiger zu vergessen sind. Auch hier ist es eine
Frage der gesunden Gründlichkeit, den immer auch auf NULL zu
setzen.

Danke für dein „Quark mit Sosse“ das bringt mich leider auch nicht weiter…

Was ich dazu jetzt noch schreiben soll weiß ich auch nicht… Am besten ich wiederhole mich für dich nochmal…

nach einem „delete ptr“ enthällt ptr immernoch eine Adresse.
Jemand hatte nicht die besagte Gründlichkeit danach ein „ptr = NULL“ zu schreiben.

So und ich hab damit zu kämpfen, dass ein Pointer der eigentlich NULL hätte sein sollen durch das ganze Progtramm geschleift wird und abstürze auslößt.

Der Code ist unübersichtlich, pro Methode gibt es weit mehr als 1 return und es werden viele Compiler-Makros verwendet…

Also eine unschöne Arbeit…

Laut deiner ViKa bist Du ja ohnedies Fachinfomatiker, da wirst du :das fraglos auch ohne mir schaffen. Was Dein Deutsch betrifft :frowning:ungültige Ausdrücke auch hier…), bin ich mir da nicht so sicher, :aber es gibt ja dafür weiter unten noch ein Brett. Dann brauchst Du :noch ein Brett für guten Benimm: Leute, die hier das nötigst drauf :haben, bedanken sich wenigstens einmal dafür, dass andere Teilnehmer :sich Mühe machen.

Im übrigen sollte ich mich noch dafür bedanken, dass du dir die Mühe gemacht hast etwas zu schreiben… Auch wenn ich eigentlich darauf verzichten hätte könenn weil weiter geholfen hast mir das nicht wirklich. Im Gegenteil ich fühle mich auch noch beleidigt von dir…
Aber da du dich offensichtlich auch von mir beleidigt fühlst würde ich mich also freuen, wenn du in Zukunft vermeiden könntest mir zu schreiben :smile:

Wer auf die Frage wie kann ich erkennen ob die Adresse in einem Pointer ein gültiges Objekt zeigt mit „frag den Pointer auf NULL ab und setzte gleich nach dem Delete die Pointervariable auf NULL“ antwortet hat mich nicht ganz richtig verstanden…

Vielen Dank

Stef

Danke :smile: Das macht das dann schon viel leicher^^