it-swarm.com.de

Ist die Adresse 0000000C eine spezielle Adresse?

Beim Programmieren brechen manchmal Dinge. Sie haben einen Fehler gemacht und Ihr Programm versucht, von einer falschen Adresse zu lesen.

Eine Sache, die mir auffällt, ist oft, dass diese Ausnahmen wie folgt sind:

Access violation at address 012D37BC in module 'myprog.exe'. Read of address 0000000C.

Jetzt sehe ich viele Fehlerprotokolle und was mir auffällt, ist: 0000000C. Ist das eine "besondere" Adresse? Ich sehe andere Zugriffsverletzungen mit schlechten Lesevorgängen, aber die Adressen scheinen nur zufällig zu sein, aber diese kommen in völlig anderen Situationen immer wieder zurück.

32
Pieter B

00000000 ist eine spezielle Adresse (der Nullzeiger). 0000000C ist genau das, was Sie erhalten, wenn Sie dem Nullzeiger einen Offset von 12 hinzufügen, höchstwahrscheinlich, weil jemand versucht hat, das z -Mitglied einer Struktur wie der folgenden durch einen Zeiger zu erhalten, der tatsächlich null war.

struct Foo {
    int w, x, y; // or anything else that takes 12 bytes including padding
    // such as: uint64_t w; char x;
    // or: void *w; char padding[8];
    // all assuming an ordinary 32 bit x86 system
    int z;
}
57
user7043

In Windows ist es illegal, die gesamte erste und letzte Seite zu dereferenzieren, dh die ersten oder letzten 64 KB des Prozessspeichers (die Bereiche 0x00000000 Bis 0x0000ffff). und 0xffff0000 bis 0xffffffff in einer 32-Bit-Anwendung).

Dies dient dazu, das undefinierte Verhalten der Dereferenzierung eines Nullzeigers oder Index in ein Nullarray abzufangen. Die Seitengröße beträgt 64 KB, sodass Windows nur verhindern muss, dass der ersten oder letzten Seite ein gültiger Bereich zugewiesen wird.

Dies schützt nicht vor nicht initialisierten Zeigern, die einen beliebigen Wert haben könnten (einschließlich gültiger Adressen).

11
ratchet freak

Warum 0x0C Häufiger zu sein scheint als 0x08 (Ist es wirklich? Ich weiß nicht; und in welchen Arten von Anwendungen?), Hat dies möglicherweise mit Zeigern virtueller Methodentabellen zu tun. Dies ist wirklich eher ein Kommentar (wildes Massenraten :), aber es ist etwas größer, also los geht's ... Wenn Sie eine Klasse mit virtuellen Methoden haben, werden ihre eigenen Felder um 0x04. Beispielsweise kann eine Klasse, die von einer anderen virtuellen Klasse erbt, ein Speicherlayout wie das folgende haben:

0x00 - VMT pointer for parent
0x04 - Field 1 in parent
0x08 - VMT pointer for child
0x0C - Field 1 in child

Ist dies ein häufiges Szenario oder sogar nahe? Ich bin mir nicht sicher. Beachten Sie jedoch, dass dies in einer 64-Bit-Anwendung noch interessanter in Richtung 0x0C Wert verschoben werden kann:

0x00 - VMT parent
0x08 - Field 1 parent
0x0C - VMT child
0x14 - Field 2 child

Es gibt also tatsächlich viele Fälle, in denen sich Anwendungen bei Nullzeiger-Offsets möglicherweise erheblich überschneiden. Dies ist möglicherweise das erste Feld in einer untergeordneten Klasse oder der Tabellenzeiger für virtuelle Methoden. Wird benötigt, wenn Sie eine virtuelle Methode für eine Instanz aufrufen. Wenn Sie also eine virtuelle Methode für einen Zeiger null aufrufen, müssen Sie ' Ich bekomme eine Zugriffsverletzung auf den VMT-Offset. Die Verbreitung dieses bestimmten Werts hat dann möglicherweise etwas mit einer allgemeinen API zu tun, die eine Klasse mit einem ähnlichen Vererbungsmuster oder eher mit einer bestimmten Schnittstelle bereitstellt (für einige Anwendungsklassen wie DirectX-Spiele durchaus möglich). Es könnte möglich sein, eine einfache häufige Ursache wie diese zu verfolgen, aber ich neige dazu, Anwendungen loszuwerden, die ziemlich schnell eine Null-Dereferenzierung durchführen, also ...

2
Luaan