Академический Документы
Профессиональный Документы
Культура Документы
http://ilay.org/yann/articles/mem/
retour
Gestion de la mmoire en C
1 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Notice
Le prsent document est publi sous la licence Verbatim Copying telle que dnie par la Free Software Fondation dans le cadre du projet GNU. Toute copie ou diusion de ce document dans son intgralit est permise (et mme encourage), quel qu'en soit le support la seule condition que cette notice, inclant les copyrights, soit prserve. Copyright (C) 2002, 2003, 2004 Yann LANGLAIS, ilay. La plus rcente version en date de ce document est sise l'url http://ilay.org /yann/articles/mem/. Toute remarque, suggestion ou correction est bienvenue et peut tre adresse Yann LANGLAIS, ilay.org.
2 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Introduction
Le langage C est souvent considr comme un langage dicile et peu able. La seconde assertion n'est pas acceptable dans la mesure o la plupart des applications, y compris les L4G et RAD sont eux mmes crits en C. En fait, ces ides reues proviennent principalement de l'utilisation intensive des pointeurs. Si le C est souvent mal considr, c'est bien souvent cause de la mconnaissance du concept de pointeur et de la gestion de la mmoire qui lui est associ. Le prsent document se propose de prsenter ces concepts depuis leurs fondements thoriques jusqu' leur application pratique. Il ne s'agit pas pour autant de dnir les direntes notions avec la plus grande rigueur qui soit. Mon propos n'est pas de faire de l'initiation l'assembleur, ni l'lectronique. Mon but est de prsenter la gestion de la mmoire sous un angle dirent de celui gnralement adopt. L'audience vise est principalement celle des dveloppeurs ayant dj t initis au langage C.
(Table des matires)
3 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
La mmoire
La mmoire physique de l'ordinateur
La mmoire de l'ordinateur est assimilable, en premire approximation un long tableau continu. La largeur de ce tableau s'exprime en "bits". En gnral, les cette taille comporte des subdivisions. En eet, pour une taille de 32bits, par exemple, un octet n'etant cod que sur 8bits, il est ncessaire, an de ne pas perdre trop d'espace, de pouvoir stocker 4 octets dirents par case de 32 bits et donc accder de manire indpendante ces 4 subdivisions. Un bus 32bits est en gnral dcoup en subdivisions de 8 et 16 bits. Chaque subdivision (octet) est numrote. Cette numrotation correspond une adresse mmoire.
4 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Zone programme
Tout d'abord la zone de "programme", dcoupe en plusieurs segments dont : Le segment texte (.text) contient le code machine du programme. Le segment bss (.bss) contient les donnes non initialises (variables globales du C). BSS signie "Block Stating Symbol". Le segment data (.data) contient les donnes initialises du programmes (constantes globales).
Le tas (heap)
Ensuite, vient le tas (heap). C'est la mmoire alloue dynamiquement avec les
5 sur 58 22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
fonctions de type malloc(). La croissance de cette zone s'eectue vers les adresses hautes. L'adresse de base du tas est donne par la fonction sbrk(0) avant toute allocation ou par brk(0).
Le mmoire libre
Vient la zone de mmoire libre", ou mmoire non alloue. Elle est consomme par le tas. La rservation d'une zone suppmentaire se fait avec la fonction sbrk(taillesupp) ou taillesup est la taille de la zone rserver.
La pile (stack)
Enn, la dernire zone de l'espace utilisateur est la pile. La pile commence, l'inverse des autres zones, l'adresse la plus haute (soit thoriquement PAGE_OFFSET-1). La pile croit donc vers les adresses basses. La pile se compose de boites ou cadres (frames). Chacune de ces boites correspont une procdure ou fonction. La fonction main() sera la boite 1 (seconde sur la pile). Si main() appelle une fonction "toto()", alors, lorsque le programme passera dans toto(), une boite numrote 2 sera place sur la pile, au "dessus" de la boite numrote 1 de main(). A la sortie de la fonction toto(), la boite numro 2 sera dtruite (dpile/modication de la topographie ou mapping de la mmoire virtelle). Chaque boite contient les variables locales la procdure (i.e. dnie sur la pile), l'adresse de retour de la procdure, une sauvegarde des paramres passe en entre la procdure, voire aussi une copie de tout ou partie de la zone de registres du microprocesseur. Une boite, ou frame, n'est donc valide que tant que l'on ne sort pas de la fonction laquelle elle est associe. Il n'est donc possible d'utiliser un pointeur sur une zone de mmoire rserve sur la pile que dans la fonction o cette mmoire est rserve et les sous fonctions appeles par cette fonction. Des la sortie d'une fonction, la zone la frame associe cette fonction est limine de la carte de la mmoire virtuelle. La zone occupe par l'ancienne frame se retrouve donc contenir des donnes alatoires. En corrolaires : La pile est rserve statiquement. Il est impossible de changer dynamiquement sa taille. Une pile est allou localement : pour le programme (variable globale non statique, ou dnie comme externe), pour le chier en cours (variable globale statique), pour la fonction en cours (variables dnies en dbut de fonction).
6 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
La pile reprsente la proportion de la mmoire de travail utilise temporairement pour un traitement particulier.
% cat frameshow.c #include int function3(int a, int b, int c, int d) { int i_3 = 0x30303030; printf("in function3\n"); return 0x3F3F3F3F; } int function2(int a, int b, int c, int d) { int i_2 = 0x20202020; printf("in function2\n"); function3(0xCCCCCCC1, 0xCCCCCCC2, 0xCCCCCCC3, 0xCCCCCCC4); return 0x2F2F2F2F; } int function1(int a, int b, int c, int d) { int i_1 = 0x10101010; printf("in function1\n"); function2(0xBBBBBBB1, 0xBBBBBBB2, 0xBBBBBBB3, 0xBBBBBBB4); return 0x1F1F1F1F; } int final(int a, int b) { int i_final = 0x0FF00FF0; return i_final; } int main() { int i_main = 0x12345678; printf("in main\n"); function1(0xAAAAAAA1, 0xAAAAAAA2, 0xAAAAAAA3, 0xAAAAAAA4); final(0xDDDDDDD1, 0xDDDDDDD2); return 0; } % cc -g frameshow.c -o frameshow % dis frameshow **** DISASSEMBLER
****
disassembly for frameshow section .text _start() 106b8: 106bc: 106c0: 106c4: 106c8: 106cc: 106d0: 106d4: 106d8:
bc e0 13 e0 a2 13 e2 13 e2
10 03 00 22 03 00 22 00 22
20 a0 00 60 a0 00 60 00 60
00 40 83 54 44 83 50 83 44
%fp [%sp + 64], %l0 %hi(0x20c00), %o1 %l0, [%o1 + 0x54] %sp, 68, %l1 %hi(0x20c00), %o1 %l1, [%o1 + 0x50] %hi(0x20c00), %o1 %l1, [%o1 + 0x44]
7 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
106dc: 106e0: 106e4: 106e8: 106ec: 106f0: 106f4: 106f8: 106fc: 10700: 10704: 10708: 1070c: 10710: 10714: 10718: 1071c: 10720: 10724: 10728: 1072c: 10730: 10734: 10738: 1073c: 10740: 10744: 10748: 1074c: 10750: 10754: 10758: 1075c: 10760: 10764: 10768: 1076c: 10770: 10774: 10778: 1077c: 10780: 10784: 10788: 1078c: 10790: 10794: 10798: 1079c: 107a0: 107a4: 107a8: 107ac: 107b0: 107b4: 107b8: 107bc: 107c0: a5 a4 a4 27 e8 80 12 01 e4 2b aa 80 02 01 ad ae ac ac ab 29 a8 c1 ec ae af af ac ac ec c1 9c 80 02 90 40 01 11 40 90 11 d0 80 12 01 11 d0 80 02 01 40 01 40 01 90 92 94 96 40 2c 04 04 00 04 a5 80 00 24 00 15 90 80 00 2d 0d 0d 15 2d 00 15 2d 05 20 3d 2d 2d 15 25 0d 23 90 80 10 00 00 00 00 12 00 02 90 80 00 00 02 90 80 00 00 00 00 00 10 10 10 10 00 20 a0 40 00 e0 20 00 00 e0 00 60 00 00 00 60 a3 60 80 a0 00 20 00 00 00 e0 e0 80 80 00 00 a0 00 00 00 40 00 00 40 22 00 20 00 00 00 00 20 00 00 00 40 00 00 00 00 00 00 00 00 02 04 12 83 38 00 03 00 38 00 00 15 12 00 02 00 3f 17 16 83 3c 00 00 17 1f 1e 17 15 00 00 20 01 04 01 f1 00 42 ee 7c 83 48 08 09 00 83 4c 08 04 00 e2 00 b2 00 10 11 12 13 88 sll add add sethi ld cmp bne nop st sethi or orcc be nop sll and and or sll sethi or st ld sub sra sll andn or st ld sub orcc be mov call nop sethi call or sethi ld orcc bne nop sethi ld orcc be nop call nop call nop mov mov mov mov call %l0, 2, %l2 %l2, 4, %l2 %l1, %l2, %l2 %hi(0x20c00), %l3 [%l3 + 0x38], %l4 %l4, 0 0x10700
http://ilay.org/yann/articles/mem/
%l2, [%l3 + 56] %hi(__fsr_init_value), %l5 %l5, __fsr_init_value, %l5 %g0, %l5, %g0 0x10754 %l5, 2, %l6 %l6, 768, %l7 %l5, 63, %l6 %l6, %l7, %l6 %l6, 22, %l5 %hi(0x20c00), %l4 %l4, 0x3c, %l4 ! __crt_scratch %fsr, [%l4] [%l4], %l6 %g0, %l7, %l7 %l7, 31, %l7 %l7, 30, %l7 %l6, %l7, %l6 %l6, %l5, %l6 %l6, [%l4] [%l4], %fsr %sp, 32, %sp %g0, %g1, %g0 0x1076c %g1, %o0 atexit %hi(0x10800), %o0 atexit %o0, 636, %o0 %hi(0x20c00), %o0 [%o0 + 0x48], %o0 %g0, %o0, %g0 0x107a8 %hi(0x20c00), %o0 [%o0 + 0x4c], %o0 %g0, %o0, %g0 0x107a8 atexit _init %l0, %l1, %l2, %l3, main %o0 %o1 %o2 %o3
! __fsr_init_va
8 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
107c4: 107c8: 107cc: 107d0: 107d4: 107d8: 107dc: 107e0: 107e4: function3() 107e8: 107ec: 107f0: 107f4: 107f8: 107fc: 10800: 10804: 10808: 1080c: 10810: 10814: 10818: 1081c: 10820: 10824: 10828: 1082c: 10830: 10834: 10838: 1083c: 10840: 10844: 10848: 1084c: function2() 10850: 10854: 10858: 1085c: 10860: 10864: 10868: 1086c: 10870: 10874: 10878: 1087c: 10880: 10884: 10888: 1088c: 10890: 10894: 10898: 1089c: 108a0: 01 40 01 40 01 00 00 00 00 9d f6 f4 f2 f0 21 a0 e0 21 a0 40 90 21 a0 10 e0 10 01 e0 b0 81 81 00 00 00 00 9d f6 f4 f2 f0 21 a0 e0 21 a0 40 90 21 a0 23 a2 25 a4 27 a6 90 00 00 00 00 00 01 01 01 01 e3 27 27 27 27 0c 14 27 00 14 00 14 0f 14 80 27 80 00 07 14 c7 e8 01 01 01 01 e3 27 27 27 27 08 14 27 00 14 00 14 0c 1c 0c 1c 0c 1c 0c 1c 14 00 40 00 40 00 00 00 00 00 bf a0 a0 a0 a0 0c 20 bf 00 22 40 00 cf 23 00 bf 00 00 bf 00 e0 00 00 00 00 00 bf a0 a0 a0 a0 08 20 bf 00 22 40 00 cc 3c cc 7c cc bc cc fc 00 00 db 00 dc 00 00 00 00 00 98 50 4c 48 44 0c 30 f8 42 b8 cf 00 cf 3f 04 fc 02 00 fc 00 08 00 00 00 00 00 98 50 4c 48 44 08 20 f8 42 c8 b5 00 cc c1 cc c2 cc c3 cc c4 00 nop call nop call nop unimp unimp unimp unimp save st st st st sethi or st sethi or call or sethi or ba st ba nop ld or ret restore unimp unimp unimp unimp save st st st st sethi or st sethi or call or sethi xor sethi xor sethi xor sethi xor or
http://ilay.org/yann/articles/mem/
exit _exit 0x10000 0x10000 0x10000 0x10000 %sp, -104, %sp %i3, [%fp + 80] %i2, [%fp + 76] %i1, [%fp + 72] %i0, [%fp + 68] %hi(0x30303000), %l0 %l0, 0x30, %l0 ! 0x30303030 %l0, [%fp - 8] %hi(0x10800), %l0 %l0, 0x2b8, %l0 ! 0x10ab8 printf %l0, %g0, %o0 %hi(0x3f3f3c00), %l0 %l0, 0x33f, %l0 ! 0x3f3f3f3f 0x10830 %l0, [%fp - 4] 0x10830 [%fp - 4], %l0 %l0, %g0, %i0
0x10000 0x10000 0x10000 0x10000 %sp, -104, %sp %i3, [%fp + 80] %i2, [%fp + 76] %i1, [%fp + 72] %i0, [%fp + 68] %hi(0x20202000), %l0 %l0, 0x20, %l0 ! 0x20202020 %l0, [%fp - 8] %hi(0x10800), %l0 %l0, 0x2c8, %l0 ! 0x10ac8 printf %l0, %g0, %o0 %hi(0x33333000), %l0 %l0, -831, %l0 %hi(0x33333000), %l1 %l1, -830, %l1 %hi(0x33333000), %l2 %l2, -829, %l2 %hi(0x33333000), %l3 %l3, -828, %l3 %l0, %g0, %o0
9 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
108a4: 108a8: 108ac: 108b0: 108b4: 108b8: 108bc: 108c0: 108c4: 108c8: 108cc: 108d0: 108d4: 108d8: 108dc: 108e0: 108e4: 108e8: 108ec: function1() 108f0: 108f4: 108f8: 108fc: 10900: 10904: 10908: 1090c: 10910: 10914: 10918: 1091c: 10920: 10924: 10928: 1092c: 10930: 10934: 10938: 1093c: 10940: 10944: 10948: 1094c: 10950: 10954: 10958: 1095c: 10960: 10964: 10968: 1096c: 10970: 10974: 10978: 1097c: 10980: 10984: 92 94 7f 96 21 a0 10 e0 10 01 e0 b0 81 81 00 00 00 00 00 9d f6 f4 f2 f0 21 a0 e0 21 a0 40 90 21 a0 23 a2 25 a4 27 a6 90 92 94 7f 96 21 a0 10 e0 10 01 e0 b0 81 81 00 00 00 14 14 ff 14 0b 14 80 27 80 00 07 14 c7 e8 01 01 01 01 01 e3 27 27 27 27 04 14 27 00 14 00 14 11 1c 11 1c 11 1c 11 1c 14 14 14 ff 14 07 14 80 27 80 00 07 14 c7 e8 01 01 01 40 80 ff c0 cb 23 00 bf 00 00 bf 00 e0 00 00 00 00 00 00 bf a0 a0 a0 a0 04 20 bf 00 22 40 00 11 3f 11 7f 11 bf 11 ff 00 40 80 ff c0 c7 23 00 bf 00 00 bf 00 e0 00 00 00 00 00 00 cf 00 cb 2f 04 fc 02 00 fc 00 08 00 00 00 00 00 00 98 50 4c 48 44 04 10 f8 42 d8 8d 00 11 b1 11 b2 11 b3 11 b4 00 00 00 c1 00 c7 1f 04 fc 02 00 fc 00 08 00 00 00 00 or or call or sethi or ba st ba nop ld or ret restore unimp unimp unimp unimp unimp save st st st st sethi or st sethi or call or sethi xor sethi xor sethi xor sethi xor or or or call or sethi or ba st ba nop ld or ret restore unimp unimp unimp
http://ilay.org/yann/articles/mem/
%l1, %g0, %o1 %l2, %g0, %o2 function3 %l3, %g0, %o3 %hi(0x2f2f2c00), %l0 %l0, 0x32f, %l0 ! 0x2f2f2f2f 0x108cc %l0, [%fp - 4] 0x108cc [%fp - 4], %l0 %l0, %g0, %i0
0x10000 0x10000 0x10000 0x10000 0x10000 %sp, -104, %sp %i3, [%fp + 80] %i2, [%fp + 76] %i1, [%fp + 72] %i0, [%fp + 68] %hi(0x10101000), %l0 %l0, 0x10, %l0 ! 0x10101010 %l0, [%fp - 8] %hi(0x10800), %l0 %l0, 0x2d8, %l0 ! 0x10ad8 printf %l0, %g0, %o0 %hi(0x44444400), %l0 %l0, -79, %l0 %hi(0x44444400), %l1 %l1, -78, %l1 %hi(0x44444400), %l2 %l2, -77, %l2 %hi(0x44444400), %l3 %l3, -76, %l3 %l0, %g0, %o0 %l1, %g0, %o1 %l2, %g0, %o2 function2 %l3, %g0, %o3 %hi(0x1f1f1c00), %l0 %l0, 0x31f, %l0 ! 0x1f1f1f1f 0x1096c %l0, [%fp - 4] 0x1096c [%fp - 4], %l0 %l0, %g0, %i0
10 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
10988: 1098c: final() 10990: 10994: 10998: 1099c: 109a0: 109a4: 109a8: 109ac: 109b0: 109b4: 109b8: 109bc: 109c0: 109c4: 109c8: 109cc: 109d0: 109d4: 109d8: 109dc: main() 109e0: 109e4: 109e8: 109ec: 109f0: 109f4: 109f8: 109fc: 10a00: 10a04: 10a08: 10a0c: 10a10: 10a14: 10a18: 10a1c: 10a20: 10a24: 10a28: 10a2c: 10a30: 10a34: 10a38: 10a3c: 10a40: 10a44: 10a48: 10a4c: 10a50: 10a54: 10a58: 10a5c: 10a60: 10a64: 9d 21 a0 e0 21 a0 40 90 21 a0 23 a2 25 a4 27 a6 90 92 94 7f 96 21 a0 23 a2 90 7f 92 10 c0 10 01 e0 b0 e3 04 14 27 00 14 00 14 15 1c 15 1c 15 1c 15 1c 14 14 14 ff 14 08 1c 08 1c 14 ff 14 80 27 80 00 07 14 bf 8d 22 bf 00 22 40 00 55 3e 55 7e 55 be 55 fe 00 40 80 ff c0 88 3d 88 7d 00 ff 40 00 bf 00 00 bf 00 98 15 78 f8 42 e8 55 00 55 a1 55 a2 55 a3 55 a4 00 00 00 b1 00 88 d1 88 d2 00 d2 00 04 fc 02 00 fc 00 save sethi or st sethi or call or sethi xor sethi xor sethi xor sethi xor or or or call or sethi xor sethi xor or call or ba st ba nop ld or 9d f2 f0 21 a0 e0 e0 10 e0 10 01 e0 b0 81 81 00 00 00 00 00 e3 27 27 03 14 27 07 80 27 80 00 07 14 c7 e8 01 01 01 01 01 bf a0 a0 fc 23 bf bf 00 bf 00 00 bf 00 e0 00 00 00 00 00 00 98 48 44 03 f0 f8 f8 04 fc 02 00 fc 00 08 00 00 00 00 00 00 save st st sethi or st ld ba st ba nop ld or ret restore unimp unimp unimp unimp unimp 00 01 00 00 00 01 00 00 unimp unimp 0x10000 0x10000
http://ilay.org/yann/articles/mem/
%sp, -104, %sp %i1, [%fp + 72] %i0, [%fp + 68] %hi(0xff00c00), %l0 %l0, 0x3f0, %l0 ! 0xff00ff0 %l0, [%fp - 8] [%fp - 8], %l0 0x109bc %l0, [%fp - 4] 0x109bc [%fp - 4], %l0 %l0, %g0, %i0
0x10000 0x10000 0x10000 0x10000 0x10000 %sp, -104, %sp %hi(0x12345400), %l0 %l0, 0x278, %l0 ! 0x12345678 %l0, [%fp - 8] %hi(0x10800), %l0 %l0, 0x2e8, %l0 ! 0x10ae8 printf %l0, %g0, %o0 %hi(0x55555400), %l0 %l0, -351, %l0 %hi(0x55555400), %l1 %l1, -350, %l1 %hi(0x55555400), %l2 %l2, -349, %l2 %hi(0x55555400), %l3 %l3, -348, %l3 %l0, %g0, %o0 %l1, %g0, %o1 %l2, %g0, %o2 function1 %l3, %g0, %o3 %hi(0x22222000), %l0 %l0, -559, %l0 %hi(0x22222000), %l1 %l1, -558, %l1 %l0, %g0, %o0 final %l1, %g0, %o1 0x10a60 %g0, [%fp - 4] 0x10a60 [%fp - 4], %l0 %l0, %g0, %i0
11 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
10a68: 10a6c: section .init _init() 10a70: 10a74: 10a78: section .fini _fini() 10a7c: 10a80: 10a84: 81 c7 e0 08 81 e8 00 00 ret restore
http://ilay.org/yann/articles/mem/
9d e3 bf a0 81 c7 e0 08 81 e8 00 00
9d e3 bf a0 81 c7 e0 08 81 e8 00 00
% dbx frameshow Reading frameshow Reading ld.so.1 Reading libc.so.1 Reading libdl.so.1 Reading libc_psr.so.1 dbx> alias P="print -f0x%x" dbx> print main main = &main() at 0x109e0 dbx> print function1 function1 = &function1(int a, int b, int c, int d) at 0x108f0 dbx> print function2 function2 = &function2(int a, int b, int c, int d) at 0x10850 dbx> print function3 function3 = &function3(int a, int b, int c, int d) at 0x107e8 dbx> stop in main (2) stop in main dbx> run Running: frameshow (process id 28873) stopped in main at line 31 in file "frameshow.c" 31 int i_main = 0x12345678; dbx> next stopped in main at line 32 in file "frameshow.c" 32 printf("in main\n"); dbx> P $sp $sp = 0xffbef3e0 dbx> P $fp $fp = 0xffbef448 dbx> ex $sp, $fp 0xffbef3e0: 0x12345678 0x00000000 0x00000000 0x00000000 0xffbef3f0: 0x00000000 0x00000000 0x00000000 0xff3dc890 0xffbef400: 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef448 0x000107c0 0xffbef410: 0xffbef420: 0x00000000 0x00000000 0x00000003 0xffbef4ac 0x00000004 0xffbef4b4 0x00000005 0xffbef5fc 0xffbef430: 0xffbef440: 0x12345678 0x00000000 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0xff319c04 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x00000000 0xff3420d8 0xff33e5d8 0xffffffff o4-o7 0x000222e8 0xff29bc20 0xffbef3e0 0xff29bc20
12 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
l0-l3 0x12345678 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0xff3dc890 i0-i3 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 i4-i7 0x00000000 0x00000000 0xffbef448 0x000107c0 y 0x00000000 ccr 0x00000000 pc 0x000109f0:main+0x10 sethi %hi(0x10800), %l0 npc 0x000109f4:main+0x14 or %l0, 0x2e8, %l0 dbx> next stopped in main at line 33 in file "frameshow.c" 33 function1(0xAAAAAAA1, 0xAAAAAAA2, 0xAAAAAAA3, 0xAAAAAAA4); dbx> step stopped in function1 at line 18 in file "frameshow.c" 18 int i_1 = 0x10101010; dbx> next stopped in function1 at line 19 in file "frameshow.c" 19 printf("in function1\n"); dbx> next stopped in function1 at line 20 in file "frameshow.c" 20 function2(0xBBBBBBB1, 0xBBBBBBB2, 0xBBBBBBB3, 0xBBBBBBB4); dbx> P $sp $sp = 0xffbef378 dbx> P $fp $fp = 0xffbef3e0 dbx> ex $sp, 0xffbef448 0xffbef378: 0x00010ad8 0x00000000 0x00000000 0x00000000 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 input parameters 0xffbef398: 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c previous stack end and return a 0xffbef3e0 0x000109f8 0x00000000 0x00000000 0xffbef3b8: 0xffbef3c8: 0x00000000 0x00000000 0x00000000 0xff29bc20 0xffbef3d8: 0x10101010 0x000109f8 0xaaaaaaa1 0xaaaaaaa2 parameters passed 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 function1 0xffbef3e8: 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef408: 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef428: 0xffbef438: 0xff29bc20 0xffbef5fc 0x12345678 0x00000000 value of i_main on stack 0x00000001 0xffbef448: dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x0000000d 0xff340284 0xff343a54 0x00000000 o4-o7 0x00000000 0x00000000 0xffbef378 0x00010918 l0-l3 0x00010ad8 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 i4-i7 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c y 0x00000000 ccr 0x00000099 pc 0x00010920:function1+0x30 sethi %hi(0x44444400), %l0 npc 0x00010924:function1+0x34 xor %l0, -0x4f, %l0 dbx> step stopped in function2 at line 11 in file "frameshow.c" 11 int i_2 = 0x20202020; dbx> next stopped in function2 at line 12 in file "frameshow.c"
13 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
12 printf("in function2\n"); dbx> next stopped in function2 at line 13 in file "frameshow.c" 13 function3(0xCCCCCCC1, 0xCCCCCCC2, 0xCCCCCCC3, 0xCCCCCCC4); dbx> P $sp $sp = 0xffbef310 dbx> P $fp $fp = 0xffbef378 dbx> ex $sp, 0xffbef448 0xffbef310: 0x00010ac8 0x00000000 0x00000000 0x00000000 0xffbef320: 0x00000000 0x00000000 0x00000000 0x00000000 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0xffbef330: 0xffbef340: 0x00000000 0x00000000 0xffbef378 0x0001094c 0xffbef350: 0xffbef5fc 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef360: 0xffbef370: 0x20202020 0x00000000 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef380: 0xffbef390: 0x00000000 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xff29bc20 0xffbef3a0: 0xffbef3b0: 0xffbef3e0 0x00010a2c 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0xffbef3c0: 0xffbef3d0: 0x00000000 0xff29bc20 0x10101010 0x000109f8 0xffbef3e0: 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0x00000000 0xff3dc890 0xffbef3f0: 0xffbef400: 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef448 0x000107c0 0xffbef410: 0xffbef420: 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xff29bc20 0xffbef5fc 0xffbef430: 0xffbef440: 0x12345678 0x00000000 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x0000000d 0xff340284 0xff343a54 0x00000000 o4-o7 0x00000000 0x00000000 0xffbef310 0x00010878 l0-l3 0x00010ac8 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 i4-i7 0x00000000 0x00000000 0xffbef378 0x0001094c y 0x00000000 ccr 0x00000099 pc 0x00010880:function2+0x30 sethi %hi(0x33333000), %l0 npc 0x00010884:function2+0x34 xor %l0, -0x33f, %l0 dbx> step stopped in function3 at line 5 in file "frameshow.c" 5 int i_3 = 0x30303030; dbx> next stopped in function3 at line 6 in file "frameshow.c" 6 printf("in function3\n"); dbx> next stopped in function3 at line 7 in file "frameshow.c" 7 return 0x3F3F3F3F; dbx> P $sp $sp = 0xffbef2a8 dbx> P $fp $fp = 0xffbef310 dbx> ex $sp, 0xffbef448 0xffbef2a8: 0x00010ab8 0x00000000 0x00000000 0x00000000
14 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0xccccccc1 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2d8: 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0x30303030 0x00000000 0xccccccc1 0xccccccc2 0xffbef308: 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0x00000000 0x00000000 0xbbbbbbb1 0xbbbbbbb2 0xffbef328: 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef348: 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0x00000000 0x20202020 0x00000000 0xffbef368: 0xffbef378: 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0xffbef398: 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xffbef3b8: 0xffbef3c8: 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0x10101010 0x000109f8 0xaaaaaaa1 0xaaaaaaa2 0xffbef3d8: 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef3f8: 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef428: 0xffbef438: 0xff29bc20 0xffbef5fc 0x12345678 0x00000000 0x00000001 0xffbef448: dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x0000000d 0xff340284 0xff343a54 0x00000000 o4-o7 0x00000000 0x00000000 0xffbef2a8 0x00010810 l0-l3 0x00010ab8 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xccccccc1 0xccccccc2 0xccccccc3 0xccccccc4 i4-i7 0x00000000 0x00000000 0xffbef310 0x000108ac y 0x00000000 ccr 0x00000099 pc 0x00010818:function3+0x30 sethi %hi(0x3f3f3c00), %l0 npc 0x0001081c:function3+0x34 or %l0, 0x33f, %l0 dbx> next stopped in function3 at line 8 in file "frameshow.c" 8 } dbx> next stopped in function2 at line 14 in file "frameshow.c" 14 return 0x2F2F2F2F; dbx> P $sp $sp = 0xffbef310 dbx> P $fp $fp = 0xffbef378 dbx> ex 0xffbef2a8, 0xffbef448 0xffbef2a8: 0x3f3f3f3f 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x3f3f3f3f 0xccccccc1 0xccccccc2
15 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef338: 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0x00000000 0x20202020 0x00000000 0xffbef368: 0xffbef378: 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef388: 0xffbef398: 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c 0xffbef3a8: 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0xffbef3c8: 0xffbef3d8: 0x10101010 0x000109f8 0xaaaaaaa1 0xaaaaaaa2 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef3f8: 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef448 0x000107c0 0x00000000 0xaaaaaaa1 0xffbef418: 0xffbef428: 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xff29bc20 0xffbef5fc 0x12345678 0x00000000 0xffbef438: 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 o4-o7 0x00000000 0x00000000 0xffbef310 0x000108ac l0-l3 0xccccccc1 0xccccccc2 0xccccccc3 0xccccccc4 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 i4-i7 0x00000000 0x00000000 0xffbef378 0x0001094c y 0x00000000 ccr 0x00000099 pc 0x000108b4:function2+0x64 sethi %hi(0x2f2f2c00), %l0 npc 0x000108b8:function2+0x68 or %l0, 0x32f, %l0 dbx> next stopped in function2 at line 15 in file "frameshow.c" 15 } dbx> next stopped in function1 at line 21 in file "frameshow.c" 21 return 0x1F1F1F1F; dbx> P $sp $sp = 0xffbef378 dbx> P $fp $fp = 0xffbef3e0 dbx> ex 0xffbef2a8, 0xffbef448 0xffbef2a8: 0x3f3f3f3f 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x3f3f3f3f 0x2f2f2f2f 0xccccccc2 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0x2f2f2f2f 0xbbbbbbb2 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0xffbef368: 0x00000000 0x00000000 0x20202020 0x2f2f2f2f
16 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
0xffbef378: 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0xffbef398: 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0xffbef3c8: 0xffbef3d8: 0x10101010 0x000109f8 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0xffbef3e8: 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef408: 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef428: 0xffbef438: 0xff29bc20 0xffbef5fc 0x12345678 0x00000000 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x2f2f2f2f 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 o4-o7 0x00000000 0x00000000 0xffbef378 0x0001094c l0-l3 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 i4-i7 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c y 0x00000000 ccr 0x00000099 pc 0x00010954:function1+0x64 sethi %hi(0x1f1f1c00), %l0 npc 0x00010958:function1+0x68 or %l0, 0x31f, %l0 dbx> next stopped in function1 at line 22 in file "frameshow.c" 22 } dbx> next stopped in main at line 34 in file "frameshow.c" 34 final(0xDDDDDDD1, 0xDDDDDDD2); dbx> step stopped in final at line 25 in file "frameshow.c" 25 int i_final = 0x0FF00FF0; dbx> next stopped in final at line 26 in file "frameshow.c" 26 return i_final; dbx> P $sp $sp = 0xffbef378 dbx> P $fp $fp = 0xffbef3e0 dbx> ex 0xffbef2a8, 0xffbef448 0xffbef2a8: 0x3f3f3f3f 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x3f3f3f3f 0x2f2f2f2f 0xccccccc2 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0x2f2f2f2f 0xbbbbbbb2 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0xffbef368: 0x00000000 0x00000000 0x20202020 0x2f2f2f2f
17 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
0xffbef378: 0x0ff00ff0 0x00000000 0x00000000 0x00000000 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0xffbef398: 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a48 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0xffbef3c8: 0xffbef3d8: 0x0ff00ff0 0x1f1f1f1f 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0xffbef3e8: 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef408: 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef428: 0xffbef438: 0xff29bc20 0x00000000 0x12345678 0x00010764 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x00000000 0x00000000 0x00000000 0x00000000 o4-o7 0x00000000 0x00000000 0xffbef378 0x00000000 l0-l3 0x0ff00ff0 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 i4-i7 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a48 y 0x00000000 ccr 0x00000099 pc 0x000109a8:final+0x18 ld [%fp - 0x8], %l0 npc 0x000109ac:final+0x1c ba final+0x2c dbx> next stopped in final at line 27 in file "frameshow.c" 27 } dbx> next stopped in main at line 35 in file "frameshow.c" 35 return 0; dbx> P $sp $sp = 0xffbef3e0 dbx> P $fp $fp = 0xffbef448 dbx> ex 0xffbef2a8, 0xffbef448 0xffbef2a8: 0x3f3f3f3f 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x3f3f3f3f 0x2f2f2f2f 0xccccccc2 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0x2f2f2f2f 0xbbbbbbb2 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0xffbef368: 0x00000000 0x00000000 0x20202020 0x2f2f2f2f 0xffbef378: 0x0ff00ff0 0x00000000 0x00000000 0x00000000 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef398: 0x0ff00ff0 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a48 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xffbef3c8: 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20
http://ilay.org/yann/articles/mem/
18 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
0xffbef3d8: 0x0ff00ff0 0x0ff00ff0 0xddddddd1 0xddddddd2 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef3f8: 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef428: 0xffbef438: 0xff29bc20 0x00000000 0x12345678 0x00010764 0x00000001 0xffbef448: dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x0ff00ff0 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 o4-o7 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a48 l0-l3 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 l4-l7 0x00000000 0x00000000 0x00000000 0xff3dc890 i0-i3 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 i4-i7 0x00000000 0x00000000 0xffbef448 0x000107c0 y 0x00000000 ccr 0x00000099 pc 0x00010a50:main+0x70 ba main+0x80 npc 0x00010a54:main+0x74 st %g0, [%fp - 0x4]
http://ilay.org/yann/articles/mem/
La mmoire C
Un programme C gre la mmoire de trois faons direntes: La mmoire globale du segment data, accessible depuis n'importe quel endroit du programme, o sont stockes les donnes statiques globales, La mmoire globale du tas, accessible depuis n'importe quel endroit du programme, o sont stockes les donnes dynamiquement alloues (malloc, ralloc, free, ...) La mmoire locale aussi appele la pile, accessible localement seulement, o sont passs les paramtres des fonctions et stockes les donnes locales et temporaires. Exemple :
#include <stdio.h> #include <stdlib.h> static int i_stat = 4; /* Stock dans le segment data */ int i_glob; /* Stock dans le segment bss */ int *pi_pg; /* Stock dans le segment bss */
/* main est stock dans le segment text de la zone de programme */ int main(int nargs, char **args) { /* paramtres nargs et args stocks dans la frame numro 1 de la p int *pi_loc; /* dans la frame 1 de la pile */ void *sbrk0; /* ncessaire pour stocker l'adresse de base avant le premier malloc */ sbrk0 = (void *) sbrk(0); if (!(pi_loc = (int *) malloc(sizeof(int) * 16)))
19 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
/* rservation de 16 x sizeof(int) sur le tas */ return 1; if (!(pi_pg = (int *) malloc(sizeof(int) * 8))) { /* rservation de 8 x sizeof(int) sur le tas */ free(pi_loc); return 2; de i_stat de i_glob de pi_pg de main de nargs de args de pi_loc (heap) = = = = = = = = = = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x (zone programme, segment data)\n", (zone programme, segment bss)\n", (zone programme, segment bss)\n", (zone programme, segment text)\n", (pile frame 1)\n", &nargs); (pile frame 1)\n", &args); (pile frame 1)\n", &pi_loc); (tas)\n", sbrk0); (tas)\n", pi_loc); (tas)\n", pi_pg); &i_stat); &i_glob); &pi_pg); main);
} printf("adresse printf("adresse printf("adresse printf("adresse printf("adresse printf("adresse printf("adresse printf("sbrk(0) printf("pi_loc printf("pi_pg free(pi_pg); free(pi_loc); return 0; }
20 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
On notera que la variables pi_pg est stocke dans le segment bss mais que les donnes pointes par la variable sont elles stockes dans le tas. De mme, la variable pi_loc est stocke sur la pile, mais les donnes vers lesquelles elle pointe sont stockes sur le tas.
A retenir : La mmoire d'un processus est assimilable un espace contigu, Cet espace est organis en dirents groupes fonctionnels, Les donnes d'un programme ne sont pas toutes stockes au mme endroit en fonction de leur porte et de leur mode de rservation.
(Table des matires)
21 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
En rsum, l'allocateur doit se charger des taches suivantes: rservation de pages mmoire auprs du noyau (brk/sbrk) segmentation et rservation de ces pages en fonction des besoins remise disposition de la mmoire prcdement alloue La rservation de pages mmoire est normalement transparent vis vis de l'utilisateur. Par contre, la rservation et la libration de la mmoire sont des oprations en interface avec le programmeur. Les points d'entre de ces deux oprations sont les fonctions malloc() et free(). A ces 2 oprations viennent s'ajouter realloc(), qui permet de modier la taille d'uen zone alloue.
Allocateur minimaliste
Voyons tout d'abord un allocateur minimaliste qui ne libre pas rellement la mmoire, mais dont nous pourrons nous servir le cas chant pour dbugger la mmoire.
Allocateur standards
L'allocateur minimaliste ne rpond pas au problme de la libration. Il a de plus l'inconvniant d'appeler des routines systmes (sbrk) peu performantes chaque malloc.
Types simples
Les types simples sont les types prdnis par le langage C: char, short, int, long, oat, double, et les pointeurs (void *). Il est noter que quel que soit le type de pointeur (char *, int * double *, void *), la taille d'encodage est toujours la mme. Aussi, un pointeur gnrique peut tre appel void *. Ces types ont des tailles xes pour une architecture donne, mais varient d'une architecture l'autre. Il semble mme que la taille d'un octet n'ai pas toujours t de 8bits2
22 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Il est impratif de ne pas supposer de leur taille si l'on recherche la portabilit. On pourra utiliser sizeof(type) en lieu et place de la taille suppose.
1 #include <stdio.h> 2 int main(void) { 3 printf("sizeof(char) 4 printf("sizeof(short) 5 printf("sizeof(int) 6 printf("sizeof(long) 7 8 9 10 11 12 13 14 15 } printf("sizeof(long long) printf("sizeof(float) printf("sizeof(double) printf("sizeof(void *) printf("sizeof(char *) printf("sizeof(int *) printf("sizeof(double *) return 0;
= = = = = = = = = = =
%d\n", %d\n", %d\n", %d\n", %d\n", %d\n", %d\n", %d\n", %d\n", %d\n", %d\n",
sizeof(char)); sizeof(short)); sizeof(int)); sizeof(long)); sizeof(long long));3 sizeof(float)); sizeof(double)); sizeof(void *)); sizeof(char *)); sizeof(int *)); sizeof(double *));
A retenir: D'un point de vue pratique, le type des donnes en mmoire est assimilable la taille des donnes Il ne faut jamais prjuger de la taille d'un type, mais utiliser sizeof() Tous les pointeurs ont la mme taille sur une architecture donne. Cette taille est cohrente avec la taille du bus mmoire.
Alignement
Comme nous l'avons vu dans la description de la mmoire virtuelle, la mmoire est comparable un tableau. On ne peut, en thorie, accder directement qu'a une case entire dont la taille correspond la taille de la mmoire (32bits). Il n'est donc pas possible d'accder directement une fraction d'une case mmoire.
23 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Or comme nous venons de le voir, les types de donns n'ont pas obligatoirement des tailles identiques la taille de la mmoire. Prennons par exemple le caractre char. Celui-ci est cod sur un seul octet. Mais, dans le cas d'une mmoire de 32bits, la taille d'une case est de 4 octets. On devra donc laisser, thoriquement, 3 octets vides. Dans la pratique, les choses sont un peu plus complexes car mme si la taille du bus mmoire est prpondrante, tous les octets sont directement numrots. Il est donc possible, par l'entremise d'outils inclus dans les microprocesseurs et les compilateurs, d'accder des donnes de 1, 2 ou 4 octets directement. Certaines architectures imposent cependant certaines contraintes d'alignement: les donnes ne peuvent tre stockes qu' des adresses multiples de la taille sur laquelle est code ces donnes et au maximum, des adresses multiples de la taille du bus.
Pour vrier si l'architecture possde une contrainte d'alignement, il sut de compiler et de lancer le programme suivant:
1 int main(void) { 2 struct s { char a, b, c, d, 3 int *pi; 4 pi = (int *) &(t.a); 5 printf("pi = %p, i = %d\n", 6 pi = (int *) &(t.b); 7 printf("pi = %p, i = %d\n", 8 pi = (int *) &(t.c); 9 printf("pi = %p, i = %d\n", 10 pi = (int *) &(t.d); 11 printf("pi = %p, i = %d\n", 12 pi = (int *) &(t.e); 13 printf("pi = %p, f = %d\n", 14 pi = (int *) &(t.f); 15 printf("pi = %p, i = %d\n", 16 pi = (int *) &(t.g); 17 printf("pi = %p, i = %d\n", 18 return 0; 19 } e, f, g, h, i, j;} t;
pi, *pi); pi, *pi); pi, *pi); pi, *pi); pi, *pi); pi, *pi); pi, *pi);
Si le programme se termine normalement, alors l'architecture n'impose pas de contrainte. Dans le cas contraire, le programme s'arrtera brutalement avec un signal de type bus error et gnrera un core.
24 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Pour linux AMD Athlon, le programme tourne normalement. Sur Solaris/UltraSparc, le programme s'arrte avec un "Bus error" ligne 5. A retenir: La mmoire est adressable de plusieurs manires direntes. Lorsque l'architecture impose des contraintes d'alignement, l'adresse d'une donne est un multiple de la taille des donnes adresses si cette taille est infrieure la taille du bus mmoire, ou multiple de la taille du bus . Nous avons vu que le typage constituait un canevas d'interprtation de la mmoire. Rciproquement, n'importe quelle zone mmoire peut tre interprte par un type ou un autre pour peu que l'alignement soit respect.
Types composs
Les types composs peuvent tre dnis comme des agrgats de types simples ou/et composs. La dnition de types composs se fait l'aide du mot rserv struct, suivi de la description des dirent composants. Ces types composs dnis par struct fonctionnent comme les types simples en
5 ce qui concerne l'assignation :
1 #include <stdio.h> 2 int main(void) { 3 struct s1 {int a, b;} A, B; 4 A.a = 1, A.b = 2, B.a = 3, B.b = 4; 5 A = B; 6 printf("A.a = %d\nA.b = %d\n", A.a, A.b); 7 return 0; 8 }
donne:
A.a = 3 A.b = 4
Par contre, il est impossible de faire des comparaisons sur ces types complexes (comme par exemple A==B). La squence des composants tient un rle important dans la dnition des types composs. En eet en raison des contraintes d'alignement prcites, les trois structures suivantes n'utiliseront pas la mme quantit de mmoire:
1 #include <stdio.h> 2 struct fin { 3 char a;
25 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 char b; char c; char d; float x; float y; float z; }; struct moyen { char a; char b; float x; char c; char d; float y; float z; }; struct large { char a; float x; char b; float y; char c; float z; char d; }; int main(void) { printf("sizeof(char) = %d\n", printf("sizeof(float) = %d\n", printf("4 * sizeof(char) + 3 * printf("sizeof(fin) = %d\n", printf("sizeof(moyen) = %d\n", printf("sizeof(large = %d\n", return 0; }
http://ilay.org/yann/articles/mem/
sizeof(char)); sizeof(float)); sizeof(float) = %d\n", 4 * sizeof(char) + 3 * sizeof( sizeof(struct fin)); sizeof(struct moyen)); sizeof(struct large));
Dans le cas de la structure n , la squence optimise la trace mmoire de la structure. Les 4 caractres sont contigus dans 1 case memoire de 32 bits, suivis de 3 oat dont la taille est ici de 4 octets chacuns.
Dans le cas de la structure large , la trace mmoire est maximale: pour chaque
26 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Dans le cas de la structure moyen , la trace mmoire n'est pas compltement optimise et les 2 couple de char sont cods sur chacun 4 octets.
A retenir: L'ordre des donnes dnies dans une structure inue sur la taille de la mmoire utilise an de respecter les contraintes d'alignement (mme si l'architecture n'en possde a priori pas). De mme que les types simples, les types complexes constituent un canevas d'interprtation de la mmoire. Rciproquement, toute zone de mmoire respectant les contraintes d'alignement peut tre interprte par une structure.
(Table des matires)
Tableaux
Les tableaux sont des zones de mmoires rserves et censes recevoir un nombre maximum prtabli de donnes d'un type prdni. Cependant, un tableau ne possde pas d'indication a priori de sa propre taille. Par exemple :
char a[4];
27 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
va rserver statiquement une zone de mmoire de la pile de 4 fois la taille d'un char . Cette zone est valide jusqu' la fermeture du bloc en cours. Elle est aussi adressable depuis des fonctions appeles par le bloc en cours:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <stdio.h> #include <string.h> void func2(char *string) { strcpy(string, "func2"); } char *func1() { char string[10]; strcpy(string, "func1"); printf("func1 (a): %s\n", string); func2(string); printf("func1 (b): %s\n", string); return string; } int main(void) { char *s; s = func1(); printf("main: %s\n", s); return 0; }
Mais il se peut aussi que le programme se termine par un core dump durant l'appel au dernier printf ligne 17 sur certaines plateformes si s est NULL. En fait, la fonction "func1()" retourne un pointeur allou dans la frame 2 (frame correspondant "func1()"). Or, ds que l'on sort de la fonction func1() pour revenir dans main, la frame 2 est dpile (changement de cartographie de la mmoire virtuelle). Les valeurs qui se trouvaient dans les variables alloues sur pile sont donc remplace de manire arbitraire.
Contraitement aux types composs, il n'est pas possible d'assigner un tableau un autre tableau. En effet, le "type tableau" ne connait pas sa taille, il ne peut pas tre manipul comme une structure.
Le type tableau est incomplet. Il n'est en fait qu'une utilisation dguise du concept de pointeur. A retenir: un tableau ne connait pas sa propre taille de manire a apriori. il n'est pas possible d'assigner un tableau un autre tableau. Comme nous le verrons au chapitre suivant, le tableau est un pointeur dguis.
Notion de pointeur
28 sur 58 22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Un pointeur est une zone de mmoire qui contient ou est suceptible de contenir une adresse mmoire. Bien qu'il existe des sous types dirents de pointeurs (void *, char *, short *, int *, long *, oat *, double *, pointeurs de pointeurs, pointeurs sur fonctions), tous ces sous types de pointeurs ont la mme taille et sont intercheangeables. Il exite deux oprations de base : & et * & pourrait encore s'crie adresse de et * pourrait s'crire valeur de Il est d'ailleurs tout fait possible d'crire des macros:
#define addressof(x) &(x) #define valueof(x) *(x)
Exemple:
int i = 1; int *pi = NULL;
pi = &i;
/* pi = addressof(i) */
*pi = 2;
/* valueof(pi) = 2 */
Pointeurs et tableaux La notion de tableau est intrinsquement lie la notion de pointeur. En eet, si l'on considre la mmoire comme un tableau, le pointeur devient une manire d'adresser ce tableau de manire absolue, alors que le tableau au sens C est adress de manire relative son dbut par un indexe. Un nom de tableau est quivalent un pointeur sur le premir lment du tableau: a[0]f est quivalent *a.
29 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
On peut aussi rfrencer le ime lment d'un tableau a de deux manire: a[i] ou *(a + i). La dnition de tableaux multidimentionnelle passe aussi de manire implicite par l'utilisation des pointeurs: Un tableau bi-dimensionnel est un tableau de pointeurs sur tableaux unidimensionnels: denition statique sur la pile:
float a[10][5];
Pointeurs et structures Les structures peuvent elles aussi tre dsignes par des pointeurs. Il est mme possible d'accder directement un champs d'une structure partir d'un pointeur sur structure. L'oprateur de membre passe alors de . -> :
struct complex {float a; float b} c, *pc; c.a = 1., c.b = 0., pc = &c; pc->a = 2., pc->b = 1.;
Mais ce ne sont pas les seules faons de rfrencer des membres de structures. En eet, il existe une macro osetof() (dnie dans stddef.h) permettant de retrouver l'oset (dcallage) d'un champ par rapport au premier lment de la structure qui le contient. A partir de ce dcallage et en oprant les recasting qui s'imposent, il est possible d'accder tous les champs d'une structure :
#include <stddef.h> #include <stdio.h> #include <string.h> int main(void) { typedef struct { int a; char b[10]; double c; } S; int a_shift, b_shift, c_shift; S s; char *p; p = (char *) &s; a_shift = offsetof(S, a); b_shift = offsetof(S, b); c_shift = offsetof(S, c); printf("offset a = %d\noffset b = %d\noffset c = %d\n", a_shift, b_shift, c_shift);
30 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
*((int *) (p + a_shift)) = 555; strcpy(p + b_shift, "abcdef"); *((double *) (p + c_shift)) = 3.14159;
http://ilay.org/yann/articles/mem/
printf("s.a = %d\ns.b = \"%s\"\ns.c = %lf\n", s.a, s.b, s.c); printf("*(int *) *(int *) (p+a_shift) = %d\n (p+a_shift), (p+b_shift), *(double *) (p+c_shift)); return 0; }
donne :
offset a = 0 offset b = 4 offset c = 16 s.a = 555 s.b = "abcdef" s.c = 3.141590 *(int *) (p+a_shift) = 555 (p+b_shift) = "abcdef" *(double *) (p+c_shift) = 3.141590
Pointeurs sur fonctions Il est possible de dnir des variable pointant sur des fonctions. Ces pointeurs sur fonctions sont la base du principe de virualisation et, de manire plus gnrale, de la rutilisation de fonctions quel que soit le type des donnes fournies. Cette rutilisation partir d'un typage faible, voire une absence de typage, constitue une implmentation plus lgante et plus concise que l'utisation des templates du C++. Il est ncessaire, lors de l'usage de pointeurs sur fonctions, de dnir un protocole spcique de passage de paramtres (nombre de ces paramtres). Le premier exemple qui vient l'esprit lorsqu'on parle de pointeur sur fonction est la fonction qsort (dont le prototype est d dans stdlib.h):
void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
Le variable de type pointeur sur fonction s'appelle compar. Utilisons la fonction qsort:
#include <stdlib.h> #include <stdio.h>
31 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
int float_comp(float *a, float *b) { if (*a > *b) return 1; if (*a < *b) return -1; return 0; }
http://ilay.org/yann/articles/mem/
void arr_print(float *arr) { int i; for (i = 0; i < 10; i++) printf("arr[%d] = %3.1f\n", i, arr[i]); } int main(void) { float arr[10] = {5.1, 4.2, 3.3, 1.4, 7.8, 2.0, 8.9, 9.7, 0.5, 6.6}; printf("Tableau initial:\n"); arr_print(arr); qsort(arr, 10, sizeof(float), float_comp); printf("\nTableau final:\n"); arr_print(arr); return 0; }
donne:
Tableau initial: arr[0] = 5.1 arr[1] = 4.2 arr[2] = 3.3 arr[3] = 1.4 arr[4] = 7.8 arr[5] = 2.0 arr[6] = 8.9 arr[7] = 9.7 arr[8] = 0.5 arr[9] = 6.6 Tableau final: arr[0] = 0.5 arr[1] = 1.4 arr[2] = 2.0 arr[3] = 3.3 arr[4] = 4.2 arr[5] = 5.1 arr[6] = 6.6 arr[7] = 7.8 arr[8] = 8.9 arr[9] = 9.7
Dans cet exemple, la fonction qsort utilise un pointeur sur une fonction de pomparaison. Nous avons vu comment dnir la foncition de comparaison (ici oat_comp) et comment la passer en paramtre la fonction qsort. La compilation du code prcdent produit nanmoins un message d'avertissement cause de la dirence de typage entre la fonction oat_comp() et la fonction attendue par qsort. Ce message peut tre limin de plusieurs facons: en modiant la dnition de la fonction oat_comp:
32 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
int float_comp(void *a, void *b) { if (*(float *)a > *(float *)b) return 1; ...
http://ilay.org/yann/articles/mem/
Il est galement possible de simplier l'criture de la seconde mthode en dnissant un type de pointeur sur fonction:
typedef int (*comp_f)(const float *, const float *);
Les pointeurs sur fonctions sont aussi trs utils pour la dnition de "classes". Les meilleurs exemples de ces techniques se trouvent dans l'implmentations des systmes de chiers du noyau Linux, ou encore dans l'architecture GTK/Gnome. En ce qui concerne le noyau Linux, on pourra regarder le header linux/fs.h, et en particulier la structure address_space_operations (noyau 2.4.18):
struct address_space_operations { int (*writepage)(struct page *); int (*readpage)(struct file *, struct page *); int (*sync_page)(struct page *); /* * ext3 requires that a successful prepare_write() call be followed * by a commit_write() call - they must be balanced */ int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); int (*commit_write)(struct file *, struct page *, unsigned, unsigned); /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ int (*bmap)(struct address_space *, long); int (*flushpage) (struct page *, unsigned long); int (*releasepage) (struct page *, int); #define KERNEL_HAS_O_DIRECT /* this is for modules out of the kernel */ int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int); };
Cette structure dnit les mthodes communes tous les systmes de chiers. Pour plus d'exemples, reportez-vous au chapitre "Exemple rcapitulatif"".
(Table des matires)
Dsignation des donnes La dsignation de donnes peut s'eectuer de plusieurs manires par valeur, par adresse Dsignation par valeur La dsignation d'une donne par sa valeur se fait soit en appelant le nom de la variable, si celle-ci n'est pas un pointeur vers la donne:
int i = 1;
33 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
i est alors mis pour 1. Si la variable est un pointeur, il est ncessaire de passer par l'opratieur valueof() (*):
int i = 1, *pi; pi = &i; /* pi = addressof(i) */
Dsignation par adresse La dsignation par adresse se fait soit en prenant l'adresse d'une variable par l'oprateur addressof() (&):
float f = 2.;
pf dsigne l'adresse de f
(Table des matires)
Passages de paramtres L'appel une fonction recopie les valeurs des paramtres sur la pile. On a donc une copie locale des donnes accessibles partir de nouveaux noms de variables, ceux dnis dans le prototype d'appel la fonction. Si une modication de la valeur d'une telle variable est faite, cette modication est locale. Si une variable passe en paramtre est un pointeur et que l'on modie la valeur pointe:
*p = valeur; /*valueof(p) = valeur */
34 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
&i = 0xbffff490 (3221222544), &j = 0xbffff494 (3221222548), &pk = 0xbffff498 (3221222552) i = 3, j = 4, pk = bffff4ac (3221222572), *pk = 3 a = 1, b = 2, c = 3
Les variables i et j sont bien locales fonction func. La modication de leur valeur n'est que locale. Par contre, le passage d'un pointeur en argument permet la modication de la valeur pointe.
(Table des matires)
Exemple rcapitulatif
Voici un petit exemple rcapitulatif. A vous de retrouver les direntes techniques vues et d'ajouter les commentaires. (ce code compile sans erreur ni warning avec gcc -Wall -ansi -pedantic)
#include <stdlib.h> #include <stdio.h> void * object_new(); void * object_destroy(void *); typedef struct { int type; void * (*destroy)(void *); void * (*new)(); } object_t, *pobject_t; object_t object_defaults() { object_t o; o.type = 1; o.new = object_new; o.destroy = object_destroy; return o; } typedef struct { object_t o; int (*get)(void *);
35 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
int (*set)(void *, int); int i; } int_t, *pint_t; void *object_destroy(void *po) { printf("destroy object_t\n"); if (!po) return NULL; free(po); return NULL; }
http://ilay.org/yann/articles/mem/
void * object_new() { pobject_t po; printf("create object_t\n"); if (!(po = (pobject_t) malloc(sizeof(object_t)))) return NULL; *po = object_defaults(); return (void *) po; } int int_get(void *pi) { if (!pi) return -1; return ((pint_t) pi)->i; } int int_set(void *pi, int i) { if (!pi) return -1; return ((pint_t) pi)->i = i; } void * int_new() { pint_t pi; printf("create int_t\n"); if (!(pi = (pint_t) malloc(sizeof(int_t)))) return NULL; pi->o = object_defaults(); pi->o.type = 2; pi->o.new = int_new; pi->i = 0; pi->get = int_get; pi->set = int_set; return pi; } int main(void) { pobject_t po; pint_t pi; po = (pobject_t) (pi = int_new()); printf("po = %p\npi = %p\n", (void *) po, (void *) pi); printf("type de po: %d\n", po->type); printf("type de pi: %d\n", pi->o.type); pi->set((void *) pi, 555); printf("valeur de pi->i printf("valeur de pi->get(pi)
36 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
printf("valeur de ((pint_t) po)->i = %d\n", ((pint_t) po)->i); printf("valeur de ((pint_t) po)->get((void *) po) = %d\n", ((pint_t) po)->get((void *) ((pobject_t) pi)->destroy((void *) pi); return 0; }
donne:
create int_t po = 0x8049aa0 pi = 0x8049aa0 type de po: 2 type de pi: 2 valeur de pi->i valeur de pi->get(pi) valeur de ((pint_t) po)->i valeur de ((pint_t) po)->get((void *) po) destroy object_t
(Table des matires)
= = = =
37 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Allocation dynamique
Lorsque les variables ont des tailles non xes ou encore ne sont pas usage local, il est sr d'utiliser l'allocation dynamique.
(Table des matires)
Comportement: Malloc prend en argument la taille de la zone mmoire dsire et retourne le pointeur sur la zone alloue ou 0 (pointeur nul) s'il n'y a pas assez d'espace mmoire contigu. Une zone mmoire fraichement alloue par malloc n'est a priori pas initialise et peut contenir n'importe quoi (donnes alatoires provenant d'anciennes applications ayant utilis le mme espace, ou donnes alatoires). Il est donc ncessaire de l'initialiser avec des valeurs appropries (par exemple 0) en fonction du type de dones inserer dans ces zones alloues et / ou en fonction des rgles de programmation utilises. On pourra initialiser l'ensemble de la zone avec la fonction memset(), recopier des zones existantes avec memcpy(), ou encore initialiser les blocs en fonction de leur dcoupage (types, structures, tableaux, ...).
A retenir: Il est impratif de toujours vrier que le pointeur allou est valide. Plus gnralement, il est toujours ncessaire de tester un pointeur pass en argument.
38 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Il ne faut jamais prjuger du contenu d'une zone mmoire aprs son allocation par malloc Il est ncessaire d'initialiser convenablement les zones de mmoire alloues
(Table des matires)
Comportement : A la dirence de malloc(), calloc() alloue un tableau de nmemb lements ayant chacun size pour taille. La mmoire alloue est initialise 0. Pour le reste, calloc() fonctionne comme malloc(): si la mmoire a bien t rserve et initialise, calloc() retourne le pointeur sur la zone. Sinon, calloc() returne 0 (pointeur nul).
(Table des matires)
Comportement : La fonction free() annule la rservation d'une zone de mmoire pointe par ptr, alloue par malloc() ou calloc() ou par toute autre fonction rservant de la mmoire, comme strdup() qui duplique une chaine de caractres. Si l'on tente de librer un espace mmoire qui n'a pas t alloue par malloc() ou calloc(), directement ou par le biais d'une fonction appelant malloc() ou calloc(), la fonction free() enverra un signal 11 (SIGSEGV Invalid memory reference ) qui terminera brutalement le programme. La fonction free() n'crase pas la mmoire de la zone.
39 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Il est fortement recommand d'annuler le pointeur qui vient d'tre libr par free(), an de ne pas tenter d'adresser un espace qui pourra tre rutilis. On pourra par exemple rcrire une fonction:
void *my_free(void *ptr) { if (ptr) free(ptr); return NULL; }
Comportement : La fonction realloc() prend en argument le pointeur sur la zone de mmoire (ptr) dont il faut modier la taille, et la nouvelle taille dsire (size). Si l'opration s'est bien passe, realloc() returne le pointeur sur la zone mmoire. Attention: il est fort possible que le nouveau pointeur soit dirent de l'ancien! En eet, si la zone mmoire doit tre augmente, et que la zone en cours n'est pas assez grande pour supporter la nouvelle taille, realloc() allouera une nouvelle zone de mmoire contigue et recopiera compltement l'ancienne zone. Il est donc impratif de ne pas adresser directement par un pointeur un espace mmoire dont la taille doit/peut tre modie par realloc:
Les zones en rouge sont des zones de mmoire occupes. La zone jaune est la zone de mmoire que nous avons rserv et modi par realloc. Si nous conservons un pointeur sur la zone avant le ralloc, ce pointeur ne sera plus utilisable aprs car in
40 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
adressera une zone non rserve et contenant des donnes alatoires. Si l'opration choue, realloc() retourne 0, mais ne dasalloue pas la zone d'origine. Il est impratif de ne pas rassigner le mme pointeur immdiatement avec le rsultat de realloc() au risque de perdre toutes les donnes en mmoire et de ne jamais pouvoir les librer. Ce qu'il ne faut pas faire:
ptr = realloc(ptr, newsize);
Comportement: memset() prend en argument le pointeur sur la zone alloue (s) initialiser, la valeur aecter toute la zone mmoire (c), et le nombre d'octets devant subir le traitement (n). Il est noter que seul le premier octet de la valeur d'initialisation est pris en compte. memset retourne le pointeur d'entre (s).
(Table des matires)
41 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Comportement: memcpy prend en entre le pointeur zone de mmoire alloue de destination, le poinrteur sur la zone de mmoire cible, et le nombre d'octets devant tre copis. memcpy retourne le pointeur de destination (dest). Attention: dest doit au minimum avoir de l'espace pour les n octets copier. Les deux zones de mmoire ne doivent pas se chevaucher (i.e. src + n < dest ou dest + n < src).
(Table des matires)
Comportement: La fonction memmove() dplace le contenu d'une zone mmoire vers une autre. Elle prend en argument le pointeur vers la zone mmoire alloue vers laquelle dplacer le contenu mmoire (dest), le pointeur vers la zone de dpart de la copie (src) et le nombre d'octets dplacer. Elle retourne le pointeur vers la zone de destination (dest). Contrairement memcpy(), il est possible que les 2 zones se supperposent.
(Table des matires)
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
rserve 50 chars pour une chaine, le caractre nul devra se trouver au plus l'index 49. Certaines fonctions ncessitent une attention toute particulire: strcpy() Prototype:
#include <string.h> char *strcpy(char *dest, const char *src);
Comportement: La fonction strcpy recopie le contenu de la chaine src vers la chaine alloue pointe par dest et retourne le pointeur vers la chaine de destination (le caractre nul est inclus dans la copie). Mais attention: il est ncessaire au pralable de s'tre assur que la taille rserv dans dest est suprieure ou gale la taille de la chaine pointe par src. Si ce n'est pas le cas, nous risquons d'avoir un crasement d'une zone mmoire. Cet crasement peut modier des donnes stockes sur la pile, ou pire, craser une partie du programme lui mme puisque la dnition de la pile prcde le code dans la mmoire. Ce dfaut est la base de la technique de piratage la plus rpendue: le pirate fournit au programme une chaine assez longue pour empiter sur le code de la fonction et contient un autre code au format binaire qui sera excut au lieu du code de la fonction (voir Linux Mag # ...) strncpy() Prototype:
#include <string.h> char *strncpy(char *dest, const char *src, size_t n);
Comportement: strncpy() prend les mmes arguments que strcpy() plus n, le nombre maximal d'octets recopier. Mais, l encore, attention car strncpy() recopie au plus n caractres sans pour autant tester que le dernier caractre copi est bien NULL. Il est donc ncessaire de s'assurer aprs un strncpy() que le dernier caractre est bien nul:
char* mystrncpy(char *dest, char *src, size_t n) { if (!dest) return 0; if (!src || n <= 1) return *dest = 0; strncpy(dest, src, n); dest[n - 1] = 0; return dest; }
43 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
strcat() Prototype:
#include <string.h> char *strcat(char *dest, const char *src);
Comportement: strcat ajoute la chaine dest la chaine src. Il est ncessaire d'tre sr d'avoir rserv assez de place dans la chaine dest pour recevoir la chaine src en plus de son contenu. De mme que pour strncpy, il existe une variation permettant de limiter la longueur de la chaine globale:
char *strncat(char *dest, const char *src, size_t n)
strncat() ne recopie que les n premiers octets de src la n de dest et ajoute 0 la n, 0 n'tant pas pris en compte dans n. Pour ne pas faire de dbordement mmoire, il faut donc que n soit gal la taille rserve de dest, diminu de strlen(dest) et encore diminu de 1 pour le caractre nul nal.
(Table des matires)
Comportement Cette fonction imprime remplit une chaine de caractres alloue (str) partir d'un format (format) et, eventuellement, des donnes (...) et retourne le nombre de caractres de la nouvelle chaine (caractre nul nal non compris). Une fois encore, aucun test n'est eectu sur la taille maximale de la chaine de caractres de destination. Pour cette fonction aussi, il existe une parade : la fonction snprintf().
int snprintf(char *str, size_t size, const char *format, ...);
snprintf() tronque la nouvelle chaine str size caractres y compris le caractre nul nal. Dans le cas o la chaine str est infrieure size, la fonction retourne la taille de str. Sinon, la taille de str est size - 1 et la fonction retourne -1. Il existe d'autres groupes de fonctions avec des proprits similaires, telles que strcmp et strncmp, strdup et strndup, vsprintf et vsnprintf (les quivalent de sprintf et snprintf mais dont le le dernier argument est une va_list (voir man vsprintf et man stdarg).
(Table des matires)
44 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Rgles de base
Eviter au maximum les variables globales et les conits possibles sur le nommage des variables globales: Les variables globales constituent une fonctionnalit parfois indispensables, mais elles ont aussi de gros travers: Elles peuvent poser des problmes dans les programmes rentrant , Elles risquent de masquer des bugs lors de passage de paramtres, Elles risquent de rentrer en conit avec d'autres variables. Si malgr tout, l'emploi de variables globales se fait sentir, il est alors prfrable de : Dnir ces variables de manire statique (static) an de restreindre la porte de la variable au chier en cours, Nommer ces variables de manire ce qu'elles aient la plus faible probabilit de renter en conit avec d'autres variables. On pourra par exemple utiliser comme prxe un code correspondant au nom du chier, et ajouter en dbut et en n de nom des _ . Cette typologie est concise et vite d'avoir ajouter un prxe de porte sur toutes les variables (l pour local et g pour global). Exemple:
static int _mod_today_;
Eviter l'allocation statique en dehors de l'utilisation locale de donnes Eviter l'allocation statique pour des tailles variables de donnes Penser au caractre nul des chaines de caractres Utiliser de prfrence les fonctions de manipulation de chaine de caractres vriant la taille des chaines alloues (strncpy, strncat, strncmp, snprinf, vsnprintf, ...) Toujours initialiser un pointeur 0 (NULL) Tester systmatiquement les pointeurs aprs malloc Tester systmatiquement les pointeurs passs en paramtres Tester que le retour de la fonction realloc n'est pas NULL Toujours dsallouer avec free() la mmoire alloue avec malloc() Toujours remettre 0 (NULL) les pointeurs dallous par free()
(Table des matires)
45 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
deref0
Pour utiliser un pointeur, il est ncessaire qu'il pointe sur une adresse correcte. Pour viter ce genre d'erreur, il est ncessaire de toujours allouer un pointeur :
char *p; p = (char *) malloc(12);
Il est aussi ncessaire de tester la cohrence (au moins partielle) d'un pointeur lorsque l'on ne sait pas quelle valeur il peut avoir :
void myfunc(char *str) { char *p; p = (char *) malloc(12); /* check p was correctly initialized : */ if (p) { ... } else { fprintf(stderr, "p was not allocated (p = %x)\n", p); perror("reason: "); } if (str) { ... } else {
46 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
fprintf(stderr, "str is null and therefore cannot be used!!!\n")
Il est important de noter qu'un pointeur non nul n'implique pas pour autant sa validit.
donne :
main: set : set : main: i i i i = = = = 2 2 3 2
Le passage par valeur recopie la valeur. Il ne faut donc pas confondre la variable i l'intrieur de la fonction set avec le i l'intrieur de la fonction main! D'ailleurs pour s'en convaincre :
#include <stdio.h> void set(int i) { printf("set : printf("set : i = 3; printf("set : } int main(void) { int i; i = 2; printf("main: printf("main: i = set(i); printf("main: i = return 0; }
donne :
main: main: set : set : set : &i = ffbef4d8 i = 2 &i = ffbef4bc i = 2 i = 3
47 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
main: i = 2
http://ilay.org/yann/articles/mem/
Si l'on veut modifer une variable dans une sous-fonction, il est ncessaire de passer le pointeur sur la variable, plutt que la variable elle mme.
#include <stdio.h> void set(int *i) { if (!i) { printf("invalid pointer\n"); return; } printf("set : i = %x\n", i); printf("set : *i = %d\n", *i); *i = 3; printf("set : *i = %d\n", *i); } int main(void) { int i; i = 2; printf("main: &i = %x\n", &i); printf("main: i = %d\n", i); set(&i); printf("main: i = %d\n", i); return 0; }
donne :
main: main: set : set : set : main: &i = ffbef4d8 i = 2 i = ffbef4d8 *i = 2 *i = 3 i = 3
48 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
} printf("b = \"%s\"\n", b); return 0; }
http://ilay.org/yann/articles/mem/
donne
a = "0123456789A" b = "0123456789A"
pour remdier au problme, on pourra, dans le cas d'une chaine de caractres, initialiser b de la manire suivante: *b = 0; ou b[0] = '\0'; Qui sont 2 expression rigoureusement quivalentes. En revanche memset(b, 0, 12); n'initialisera pas seulement le 1er octet de la chaine 0, mais les 12 octets rservs.
49 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
(process id 26360) stopped in main at line 13 in file "addpile.c" 13 str = init_string(); dbx% ex $sp/64 0xffbef3f8: 0xff33c5a8 0x00000000 0x00000000 0x00000000 0xffbef408: 0x00000000 0x00000000 0x00000000 0xff3e66b4 0xffbef418: 0x00000001 0xffbef4c4 0xffbef4cc 0x00020800 0xffbef428: 0x00000000 0x00000000 0xffbef460 0x00010738 0xffbef438: 0x00000000 0x00000000 0x00000003 0xffbef4c4 0xffbef448: 0x00000004 0xffbef4cc 0x00000005 0xffbef610 0xffbef458: 0x00000000 0x00000000 0x00000001 0xffbef4c4 0xffbef468: 0xffbef4cc 0x00020800 0xffbef4cc 0x00000000 0xffbef478: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef488: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef498: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef4a8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef4b8: 0x00000000 0x00000000 0x00000001 0xffbef688 0xffbef4c8: 0x00000000 0xffbef6aa 0xffbef6b7 0xffbef7af 0xffbef4d8: 0xffbef7ba 0xffbef7e6 0xffbef7f1 0xffbef7fc 0xffbef4e8: 0xffbef80d 0xffbef819 0xffbef825 0xffbef846 dbx% p &str &str = 0xffbef458 dbx% step stopped in init_string at line 5 in file "addpile.c" 5 strcpy(buff, "premire chaine"); dbx% dbx% print &buff &buff = 0xffbef3e4 dbx% ex $sp/64 0xffbef380: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef390: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef3a0: 0x00000000 0xff340060 0xff33c590 0x00000300 0xffbef3b0: 0x000239b0 0xff29bb60 0xffbef3f8 0x000107f4 0xffbef3c0: 0x00000000 0xffbef4c4 0xffbef4cc 0x00010034 0xffbef3d0: 0xff3b10f0 0x000006ee 0xff3e6da4 0xff3b17de 0xffbef3e0: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0xff33c5a8 0x00000000 0xffbef3f0: 0xffbef400: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef410: 0x00000000 0xff3e66b4 0x00000001 0xffbef4c4 0xffbef420: 0xffbef4cc 0x00020800 0x00000000 0x00000000 0xffbef430: 0xffbef460 0x00010738 0x00000000 0x00000000 0xffbef440: 0x00000003 0xffbef4c4 0x00000004 0xffbef4cc 0xffbef450: 0x00000005 0xffbef610 0x00000000 0x00000000 0xffbef460: 0x00000001 0xffbef4c4 0xffbef4cc 0x00020800 0xffbef470: 0xffbef4cc 0x00000000 0x00000000 0x00000000 dbx% n stopped in init_string at line 6 in file "addpile.c" 6 return buff; dbx% ex $sp/64 0xffbef380: 0xffbef3e4 0x0001086c 0x00000000 0x00000000 0xffbef390: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef3a0: 0x00000000 0xff340060 0xff33c590 0x00000300 0xffbef3b0: 0x000239b0 0xff29bb60 0xffbef3f8 0x000107f4 0xffbef3c0: 0x00000000 0xffbef4c4 0xffbef4cc 0x00010034 0xffbef3d0: 0xff3b10f0 0x000006ee 0xff3e6da4 0xff3b17de 0xffbef3e0: 0x00000000 0x7072656d 0x69687265 0x20636861 0xffbef3f0: 0x696e6500 0x00000000 0xff33c5a8 0x00000000 0xffbef400: 0x00000000 0x00000000 0x00000000 0x00000000
http://ilay.org/yann/articles/mem/
str area
buff area
50 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
0xffbef410: 0x00000000 0xff3e66b4 0x00000001 0xffbef4c4 0xffbef420: 0xffbef4cc 0x00020800 0x00000000 0x00000000 0xffbef430: 0xffbef460 0x00010738 0x00000000 0x00000000 0xffbef440: 0x00000003 0xffbef4c4 0x00000004 0xffbef4cc 0xffbef450: 0x00000005 0xffbef610 0x00000000 0x00000000 0xffbef460: 0x00000001 0xffbef4c4 0xffbef4cc 0x00020800 0xffbef470: 0xffbef4cc 0x00000000 0x00000000 0x00000000 dbx% ex 0xffbef3e4 0xffbef3e4: 0x7072656d dbx% n stopped in init_string at line 7 in file "addpile.c" 7 } dbx% n stopped in main at line 14 in file "addpile.c" 14 print_string(str); dbx% print -f%x $sp $sp = ffbef3f8 dbx% ex 0xffbef380/64 0xffbef380: 0xffbef3e4 0x0001086c 0x00000000 0x00000000 0xffbef390: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef3a0: 0xffbef3e4 0xff340060 0xff33c590 0x00000300 0xffbef3b0: 0x000239b0 0xff29bb60 0xffbef3f8 0x000107f4 0xffbef3c0: 0x00000000 0xffbef4c4 0xffbef4cc 0x00010034 0xffbef3d0: 0xff3b10f0 0x000006ee 0xff3e6da4 0xff3b17de 0xffbef3e0: 0x00000000 0x7072656d 0x69687265 0x20636861 0xffbef3f0: 0x696e6500 0xffbef3e4 0xff33c5a8 0x00000000 0xffbef400: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef410: 0x00000000 0xff3e66b4 0x00000001 0xffbef4c4 0xffbef420: 0xffbef4cc 0x00020800 0x00000000 0x00000000 0xffbef430: 0xffbef460 0x00010738 0x00000000 0x00000000 0xffbef440: 0x00000003 0xffbef4c4 0x00000004 0xffbef4cc 0xffbef450: 0x00000005 0xffbef610 0xffbef3e4 0x00000000 0xffbef460: 0x00000001 0xffbef4c4 0xffbef4cc 0x00020800 0xffbef470: 0xffbef4cc 0x00000000 0x00000000 0x00000000 dbx% p str p str str = 0xffbef3e4 "premire chaine" dbx% s stopped in print_string at line 9 in file "addpile.c" 9 printf("string is = \"%s\"\n", str); dbx% print -f%x $sp $sp = ffbef398 dbx% ex 0xffbef380/64 0xffbef380: 0xffbef3e4 0xffbef390: 0x00000000 0xffbef3a0: 0x00000000 0xffbef3b0: 0x00000000 0xffbef3c0: 0xff33c590 0xffbef3d0: 0xffbef3f8 0xffbef3e0: 0x00000000 0xffbef3f0: 0x696e6500 0xffbef400: 0x00000000 0xffbef410: 0x00000000 0xffbef420: 0xffbef4cc 0xffbef430: 0xffbef460 0xffbef440: 0x00000003 0xffbef450: 0x00000005
http://ilay.org/yann/articles/mem/
0x0001086c 0x00000000 0x00000000 0x00000000 0x00000300 0x00010804 0x7072656d 0xffbef3e4 0x00000000 0xff3e66b4 0x00020800 0x00010738 0xffbef4c4 0xffbef610
0x00000000 0x00000000 0x00000000 0xffbef3e4 0x000239b0 0xff3e6da4 0x69687265 0xffbef3e4 0x00000000 0x00000001 0x00000000 0x00000000 0x00000004 0xffbef3e4
0x00000000 0x00000000 0x00000000 0xff340060 0xff29bb60 0xff3b17de 0x20636861 0x00000000 0x00000000 0xffbef4c4 0x00000000 0xffbef3e4 0xffbef4cc 0x00000000
51 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
0xffbef460: 0x00000001 0xffbef4c4 0xffbef4cc 0x00020800 0xffbef470: 0xffbef4cc 0x00000000 0x00000000 0x00000000 dbx% n string is = "" stopped in print_string at line 10 in file "addpile.c" 10 } dbx% ex 0xffbef380/64 0xffbef380: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef390: 0xffbef398 0x000107c8 0x0001087c 0xffbef3e4 0xffbef3a0: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef3b0: 0x00000000 0x00000000 0xffbef3e4 0xff340060 0xffbef3c0: 0xff33c590 0x00000300 0x000239b0 0xff29bb60 0xffbef3d0: 0xffbef3f8 0x00010804 0xff3e6da4 0xff3b17de 0xffbef3e0: 0xffbef3e4 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef3e4 0xffbef3e4 0x00000000 0xffbef3f0: 0xffbef400: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef410: 0x00000000 0xff3e66b4 0x00000001 0xffbef4c4 0xffbef420: 0xffbef4cc 0x00020800 0x00000000 0x00000000 0xffbef430: 0xffbef460 0x00010738 0x00000000 0xffbef3e4 0xffbef440: 0x00000003 0xffbef4c4 0x00000004 0xffbef4cc 0xffbef450: 0x00000005 0xffbef610 0xffbef3e4 0x00000000 0xffbef460: 0x00000001 0xffbef4c4 0xffbef4cc 0x00020800 0xffbef470: 0xffbef4cc 0x00000000 0x00000000 0x00000000 dbx%
http://ilay.org/yann/articles/mem/
abracadabra...
On voit trs nettement sur cet exemple que la pile est assez versatile. La frame de la fonction init_string() est rutilise, donc crase, par la frame de la fonction print_string(). Le persistance des donnes pointes par la variable str dans la fonction main() n'est que fortuite. L'utilisation de pointeur sur une variable de pile n'est possible que dans les sous fonctions de la fonction o la variable sur pile est dnie. En eet, la frame de la pile d'une fonction n'est persistante QUE tant que l'on n'est pas encore ressorti de la fonction.
52 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
static char buff[5]; static char oops[5]; int main(void) { strcpy(buff, "0123"); *oops = 0; printf("buff = \"%s\"\noops strcpy(oops, "oops"); printf("buff = \"%s\"\noops strcpy(buff, "01234"); printf("buff = \"%s\"\noops strcpy(buff, "012345"); printf("buff = \"%s\"\noops return 0; } ^D % cc -g bss_leak.c -o bss_leak
= \"%s\"\n", buff, oops); = \"%s\"\n", buff, oops); = \"%s\"\n", buff, oops); = \"%s\"\n", buff, oops);
Vrions que les variables sont bien dnies dans le segment .bss :
% elfdump bss_leak | egrep "buff|oops" [11] 0x00020a5d 0x00000005 OBJT GLOB [19] 0x00020a58 0x00000005 OBJT GLOB [53] 0x00020a5d 0x00000005 OBJT GLOB [61] 0x00020a58 0x00000005 OBJT GLOB [11] $XAhCA_K7TOEBklT.oops [19] $XAhCA_K7TOEBklT.buff D D D D 0 0 0 0 .bss .bss .bss .bss $XAhCA_K7TOEBklT.oops $XAhCA_K7TOEBklT.buff $XAhCA_K7TOEBklT.oops $XAhCA_K7TOEBklT.buff
L'criture dans bu dpasse la taille dnie pour buff. Comme oops est localis la suite de buff, les octets surnumraires se retrouvent dans oops.
% dbx bss_leak Reading bss_leak Reading ld.so.1 Reading libc.so.1 Reading libdl.so.1 Reading libc_psr.so.1 dbx% stop in main (2) stop in main dbx% run Running: bss_leak (process id 12257) stopped in main at line 8 in file "bss_leak.c" 8 strcpy(buff, "0123"); dbx% p &buff &buff = 0x20a58 dbx% p &oops &oops = 0x20a5d
53 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
dbx% ex 0x20a58/3 0x00020a58: buff : 0x00000000 0x00000000 0x00000000 dbx% next stopped in main at line 9 in file "bss_leak.c" 9 *oops = 0; dbx% ex 0x20a58/3 0x00020a58: buff : 0x30313233 0x00000000 0x00000000 La chaine buff contient "0123" et est termine par un caractre nul dbx% next stopped in main at line 10 in file "bss_leak.c" 10 printf("buff = \"%s\"\noops = \"%s\"\n", buff, oops); dbx% next buff = "0123" oops = "" stopped in main at line 11 in file "bss_leak.c" 11 strcpy(oops, "oops"); dbx% next stopped in main at line 12 in file "bss_leak.c" 12 printf("buff = \"%s\"\noops = \"%s\"\n", buff, oops); dbx% ex 0x20a58/3 0x00020a58: buff : 0x30313233 0x006f6f70 0x73000000 la chaine oops contient maintenant "oops" et est terminue par un caractre nul dbx% next next buff = "0123" oops = "oops" stopped in main at line 13 in file "bss_leak.c" 13 strcpy(buff, "01234"); dbx% next stopped in main at line 14 in file "bss_leak.c" 14 printf("buff = \"%s\"\noops = \"%s\"\n", buff, oops); dbx% ex 0x20a58/3 0x00020a58: buff : 0x30313233 0x34006f70 0x73000000 le caractre nul de la chaine buff est positionn sur le premier caractre de la chaine oops, qui semble maintenant vide dbx% next buff = "01234" oops = "" stopped in main at line 15 in file "bss_leak.c" 15 strcpy(buff, "012345"); dbx% next stopped in main at line 16 in file "bss_leak.c" 16 printf("buff = \"%s\"\noops = \"%s\"\n", buff, oops); dbx% ex 0x20a58/3 0x00020a58: buff : 0x30313233 0x34350070 0x73000000 la chaine buff contient maintenant "012345", mais le 5 et le caractre nul son situs sur les 2 premiers caractres de la chaine oops dbx% next buff = "012345" oops = "5" stopped in main at line 17 in file "bss_leak.c" 17 return 0;
54 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
55 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
56 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Notes
1 voir "Linux Kernel Hacker's Guide" l'url http://en.tldp.org/LDP/khg/HyperNews /get/khg.html ou encore "the Linux Kerneli" http://en.tldp.org/LDP/khg/HyperNews/get/khg.html 2Brian W. Kernigan et Dennis M. Richie, dans "The C Programming Language font tat au chapitre 2.2, page 34 de la premire dition, 1978, d'une taille de 9bits pour les char sur les machines de type Honeywell 6000 3Le type long long a t introduit dans la version ANSI C99 des spcication ANSI pour le langage C 4Ces adresses sont donnes titre d'exemple. Elle peuvent varier d'un programme un autre et d'une machine une autre. 4Cette fonctionnalit n'tait pas prsente la base, mais prvue (cf. Brian W. Kernighan & Dennis M. Richie dans The C Programming Language paragraphe 14.1 de la page 209 de premire dition 1978): Other opterations, such as assigning from or to it or passing it as a parameter, draw an error message. In the future, it is expected that these operations, but not necessarily others, will be allowed Les autres oprations, comme l'assignation depuis ou vers une structure, ou le passage d'une structure en paramtre [d'une fonction] gnrent un message d'erreur. Il est vraissemblable que ces oprations, mais pas ncessairement d'autres, viendront tre autorises Cette fonctionnalit est apparue avec le standard ANSI C89..
(Table des matires)
57 sur 58
22/01/2013 22:46
Gestion de la mmoire en C
http://ilay.org/yann/articles/mem/
Rfrences
The C Programming Language, Brian W. Kernigan et Dennis M. Richie, ISBN 0131101633, 1978, Prentice-Hall LE LANGAGE C, NORME ANSI, Brian W. Kernigan et Dennis M. Richie, ISBN 2100051164, 2me dition, 1997, Dunod.
(Table des matires)
58 sur 58
22/01/2013 22:46