Le débordement de tampon modifie-t-il le type de données de la variable qu'il remplace? [fermé]

8

Dire que j'ai un tableau de caractères C char buf[15]. La variable Say int set_me = 0a ses données stockées dans un emplacement de mémoire directement après char buf[15]. Si je débordais bufde ficelle "aaabbbcccdddeee\xef\xbe\xad\xde",set_me le type de données changerait-il d'un entier à un tableau de caractères?

Darien Springer
la source
3
Dépend de qui interprète les données. enfin tout est binaire. Donc, la façon dont vous l'interprétez, cela peut être une valeur entière valide ou provoquer une erreur de
transtypage

Réponses:

33

Non.

Le "type de données" d'une variable n'est pertinent que dans le code source (et même alors seulement dans certaines langues). Il indique au compilateur comment traiter la variable.

Ces types de données de haut niveau n'existent pas en tant que tels dans le code compilé (natif). Ils peuvent affecter les instructions qu'un compilateur génère, mais les instructions elles-mêmes ne se soucient pas si les données représentent un caractère ou un nombre.


Les variables n'existent pas dans le matériel. Dans le matériel, vous avez des emplacements de mémoire et les instructions qui les concernent.

Une variable peut être vue comme une vue des données à un emplacement mémoire - si vous plissez les yeux et regardez la même mémoire légèrement différemment (une variable différente avec un type différent se référant au même emplacement), la même valeur binaire peut avoir une signification différente .

Par exemple, l'octet 0x41 pourrait être interprété comme le caractère codé UTF-8 A. Il pourrait également être interprété comme l'entier à un octet 65. Il peut également être interprété comme un octet dans un entier à plusieurs octets ou un nombre à virgule flottante, ou un octet dans un codage de caractères à plusieurs octets. Ce pourrait être le jeu de bits 0b1000001. Tous à partir du même octet dans le même emplacement de mémoire. En langage C, vous pouvez voir cet effet en effectuant un cast sur ces différents types.

Lorsque vous avez un "débordement de tampon", vous faites quelque chose en dehors des limites de ce à quoi votre compilateur ou votre langage peut s'attendre. Mais, en ce qui concerne le matériel 1 , vous écrivez des octets (simples ou multiples) dans un emplacement mémoire. Un emplacement mémoire n'a pas de "type". En fait, le matériel ne sait même pas qu'un ensemble particulier d'octets crée un tableau ou un tampon dans votre code.

Où que vous accédiez à cet emplacement de mémoire dans votre code, les instructions s'exécuteront comme défini à l'origine. par exemple, s'ils s'attendaient à un nombre, ils agiront sur tous les octets de données comme s'ils étaient un nombre.


Pour utiliser votre exemple, en supposant que votre intest un entier signé sur 4 octets (32 bits):

+-------------+--------------------------------------------+-----------+
| Source code |                  char[15]                  |    int    |
+-------------+--------------------------------------------------------+
| Memory      |61|61|61|62|62|62|63|63|63|64|64|64|65|65|65|EF|BE|AD|DE|
+-------------+--------------------------------------------------------+

Vous pouvez voir que l' intemplacement mémoire du contient maintenant 0xEFBEADDE, en supposant un système big-endian 2 . Il s'agit de l'intégré 32 bits signé -272716322. Maintenant, si vous interprétez la même mémoire comme un int ( uint) non signé , ce serait à la 4022250974place. Pour exactement les mêmes données en mémoire, la signification dépend entièrement de la façon dont vous les voyez.


1 Certains mécanismes vous empêchent d'écrire dans des régions protégées de la mémoire et plantent votre programme si vous essayez de le faire.

2 x86 est en fait peu-endian, ce qui signifie que vous interprétez les octets constituant une plus grande valeur à l'envers. Donc, sur x86, vous auriez à la place 0xDEADBEEF, donnant signé -559038737ou non signé 3735928559.

Bob
la source
Donc 0xdeadbeef, sur une architecture x86, prendrait moins de place en mémoire que son homologue décimal, 3735928559?
Darien Springer
2
@DarienSpringer Les deux prennent 4 octets de mémoire - ils sont la même séquence de 4 octets. Ils sont identiques en mémoire. Vous pouvez considérer que tout cela est en base 2 (binaire) en mémoire, si vous le souhaitez. Ensuite, lorsque vous les affichez (convertissez en une chaîne pour la sortie), vous pouvez choisir une base à afficher - l'hex est la base 16 et la décimale est la base 10. Les représentations des chaînes sont stockées dans un emplacement mémoire différent et peuvent utiliser différentes quantités de mémoire (car chaque caractère est un octet distinct). La chaîne 0xDEADBEEF est stockée en mémoire sous la forme 0x30 0x78 0x44 0x45 0x41 0x44 0x42 0x45 0x45 0x46.
Bob
5
@DarienSpringer Autrement dit, un nombre est le même quel que soit la base dans laquelle il se trouve. Hex est un moyen pratique (compact) de visualiser le binaire. Physiquement, c'est binaire. Les humains aiment la décimale, donc nous affichons plus souvent les nombres en décimal. Mais jusqu'à ce que nous arrivions à l'étape d'affichage, toutes les opérations numériques (addition, soustraction, multiplication, etc.) fonctionnent sur les mêmes données binaires en mémoire.
Bob
1
"Vous pouvez voir que l'emplacement de la mémoire de l'int est désormais 0xEFBEADDE" Nitpick: Je sais que vous ne vouliez pas cela, mais il semble que vous disiez que l'int est situé à l'emplacement de la mémoire 0xEFBEADDE. Peut-être reformulez-le un peu. Sinon, c'est une superbe réponse - j'aime particulièrement l'analogie "voir" et l'idée "plisser les yeux" :)
Courses de légèreté en orbite
@LightnessRacesinOrbit Bon point. Édité.
Bob
2

Du point de vue C, la réponse serait "Qui sait? C'est un comportement indéfini".

Les types sont un concept C, pas du matériel. Mais les règles C ne s'appliquent pas si votre programme a un comportement indéfini, c'est la signification littérale du comportement indéfini dans la norme C. Et les dépassements de tampon en sont une forme.

J'ai d'abord écrit "les règles C ne s'appliquent plus", mais en fait le comportement indéfini est rétroactif. Les règles C ne s'appliquent pas à un programme qui aura un comportement indéfini à l'avenir.

MSalters
la source