Lors de la programmation, parfois les choses se cassent. Vous avez fait une erreur et votre programme essaie de lire à partir d'une mauvaise adresse.
Une chose qui me semble que souvent ces exceptions sont comme:
Access violation at address 012D37BC in module 'myprog.exe'. Read of address 0000000C.
Maintenant, je vois beaucoup de journaux d'erreurs et ce qui me semble être le: 0000000C. S'agit-il d'une adresse "spéciale"? Je vois d'autres violations d'accès avec de mauvaises lectures mais les adresses semblent tout simplement aléatoires, mais celle-ci revient sans cesse dans des situations totalement différentes.
00000000
est une adresse spéciale (le pointeur nul). 0000000C
est exactement ce que vous obtenez lorsque vous ajoutez un décalage de 12 au pointeur nul, très probablement parce que quelqu'un a essayé d'obtenir le membre z
d'une structure comme celle ci-dessous via un pointeur qui était en fait nul.
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;
}
Sous Windows, il est interdit de déréférencer les première et dernière page entières , c'est-à-dire le premier ou le dernier 64 Ko de la mémoire de processus (les plages 0x00000000
à 0x0000ffff
et 0xffff0000
à 0xffffffff
dans une application 32 bits).
C'est pour piéger le comportement indéfini de déréférencer un pointeur ou un index nul dans un tableau nul. Et la taille de la page est de 64 Ko, donc Windows n'a qu'à empêcher que la première ou la dernière page se voit attribuer une plage valide.
Cela ne protégera pas contre les pointeurs non initialisés qui pourraient avoir n'importe quelle valeur (y compris les adresses valides).
Quant à savoir pourquoi 0x0C
semble plus courant que 0x08
(est-ce vraiment? Je ne sais pas; et dans quels types d'applications?), cela pourrait avoir à voir avec les pointeurs de table de méthode virtuelle. C'est vraiment plus un commentaire (deviner la masse sauvage :), mais c'est un peu plus grand, alors voici ... Si vous avez une classe avec des méthodes virtuelles, ses propres champs vont être décalés de 0x04
. Par exemple, une classe qui hérite d'une autre classe virtuelle peut avoir une disposition de mémoire comme celle-ci:
0x00 - VMT pointer for parent
0x04 - Field 1 in parent
0x08 - VMT pointer for child
0x0C - Field 1 in child
Est-ce un scénario courant, voire proche? Je ne suis pas sûr. Cependant, notez que dans une application 64 bits, cela pourrait devenir encore plus intéressant vers le 0x0C
valeur:
0x00 - VMT parent
0x08 - Field 1 parent
0x0C - VMT child
0x14 - Field 2 child
Il y a donc en fait beaucoup de cas où les applications peuvent avoir un chevauchement important dans les décalages de pointeur nul. Il peut s'agir du premier champ d'une classe enfant ou de son pointeur de table de méthode virtuelle - nécessaire chaque fois que vous appelez une méthode virtuelle sur une instance, donc si vous appelez une méthode virtuelle sur un pointeur null
, vous ' ll obtiendra une violation d'accès sur son offset VMT. La prévalence de cette valeur particulière pourrait alors avoir quelque chose à voir avec une API commune qui fournit une classe qui a un modèle d'héritage similaire, ou plus probablement, une interface particulière (tout à fait possible pour certaines classes d'applications, comme les jeux DirectX). Il pourrait être possible de suivre une cause commune simple comme celle-ci, mais j'ai tendance à me débarrasser des applications qui font un déréférencement nul assez rapidement, alors ...