Si tu es en train d'écrire des remplacements pour malloc et cie, que ce soit des wrappers ou pas, tu as intérêt à faire attention à l'alignement.Envoyé par Emmanuel Delahaye
Si tu es en train d'écrire des remplacements pour malloc et cie, que ce soit des wrappers ou pas, tu as intérêt à faire attention à l'alignement.Envoyé par Emmanuel Delahaye
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
dsl pour cette question mais comment isole ton le code ? le #if 0 #endif je ne connais pas...
par contre pour le realloc, jai testé des fonctions avec des listes chainées.. Lors d'un malloc, je créé une nouvelle structure contenant le pointeur et la taille et lors du free, je parcours la liste pour chercher le pointeur en question et ainsi récupérer la taille..
Ca fonctionne et me permet de conaitre la taille memoire totale allouée a chaque appel de malloc..
D'autre part, le debordement m'étonne vraiment, meme si je ne doute pas de votre avis, car ce bug intervient tres aleatoirement... et parfois au tout debut du programme...
Ce n'est rien d'autre que tu pré-processeur:Envoyé par gdpasmini
Tu entoures un code que tu ne veux pas exécuter par exemple, comme tu le fairais en le mettant en commentaire mais cette façon est bien mieux
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 #if 0 /* code a ne pas executer par exemple. */ #endif
Mon Site
Ma bibliothèque de gestion des chaînes de caractères en C
L'imagination est plus importante que le savoir. A. Einstein
Je ne répond à aucune question technique par MP, merci d'avance !
OK.Envoyé par gdpasmini
Voilà qui devrait accelérer les recherches...D'autre part, le debordement m'étonne vraiment, meme si je ne doute pas de votre avis, car ce bug intervient tres aleatoirement... et parfois au tout debut du programme...
Pas de Wi-Fi à la maison : CPL
Exact. La documentation de la GLibC spécifie même, si je ne me trompe pas, que les adresses retournées par malloc sont toujours alignées sur des frontières de mots mémoire. Dans la doc, il précisent la valeur 8 (8 caractères, j'entends), de mémoire.Envoyé par Jean-Marc.Bourguet
Une petite question : j'ai déjà écrit ma propre version de malloc et free, grâce à un algorithme entièrement personnel, et qui donne d'excellents résultats (aussi bons, voire même meilleurs dans le cas moyen que les fonctions de la GLibC... mais pas aussi paramètrables, pour l'instant). Quelle est le type à choisir pour forcer l'alignement ? Plus précisément : on suppose que l'on alloue par blocs, de taille fixée déterminée par le type contenant le cartouche et le type forçant l'alignement mémoire. Classiquement :
Le problème est qu'il est écrit dans le K&R que le type permettant de forcer l'alignement est dépendant de l'implantation. Sur mon ordi, j'utilise le type long, mais le K&R fait aussi référence au type long double (qui a de fortes chances d'être sur 80 bits avec un x86), alors qu'il me faudrait un type portable...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 /* cartouche_t est le type des cartouches */ typedef cartouche_t; /* align_t est le type forçant l'alignement */ typedef align_t; /* type des blocs : on prend une union pour forcer l'alignement mémoire */ union { align_t align; cartouche_t cartouche } bloc_t;
Connaissez-vous un type défini dans un .h standard, ou autre, permettant de forcer l'alignement, de sorte à être un maximum portable ?
When Colt produced the first practical repeating handgun, it gave rise to the saying God created men, but Colt made them equal.
Je pense que l'idée, c'est de prendre le type simple le plus grand. Pour ça, il faut étudier la doc de chaque compilateur. Ca ne peut pas être portable.Envoyé par InOCamlWeTrust
Cependant, il est possible qu'en C99, il existe un type portable qui réponde à la question. Mais C99 n'est pas disponible partout et Microsoft et Borland semblent l'ignorer...
Effectivement, dans le très C99 <stdint.h>, on trouve des choses genre
7.18.1.5 Greatest-width integer types
1 The following type designates a signed integer type capable of representing any value of
any signed integer type:
intmax_t
The following type designates an unsigned integer type capable of representing any value
of any unsigned integer type:
uintmax_t
These types are required.
Pas de Wi-Fi à la maison : CPL
Oui, je vois, c'est bien ce que je pensais.
Merci quand même !
When Colt produced the first practical repeating handgun, it gave rise to the saying God created men, but Colt made them equal.
Ca, c'est très fort, je trouve !Envoyé par Emmanuel Delahaye
When Colt produced the first practical repeating handgun, it gave rise to the saying God created men, but Colt made them equal.
La norme impose à malloc de retourner un pointeur valable pour le type le plus contraint.Envoyé par InOCamlWeTrust
En C, il n'y a pas moyen. En C++ il y a un template alignment_of dans TR1 et il devrait être repris dans la future norme.Connaissez-vous un type défini dans un .h standard, ou autre, permettant de forcer l'alignement, de sorte à être un maximum portable ?
En attendant, il faut te bâtir une union avec tous les types dedans... En C90, il est raisonnable de te limiter à long, void*, long double avec le risque qu'une extension (par exemple long long) casse ce que tu as fais. En C99 intmax_t, long double, void* devrait suffire avec moins de risques qu'une extension casse.
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
C'est une piste, oui et non, car a la base, la fonction dans laquelle le programme plante est une fonction d'une librairie open source stable et non soumis au bug... a priori..
Seulement, je l'utilise dans des interuptions et non dans des threads que cette librairie utilise normalement..
On peut donc penser, si l'on fait confiance en cette librairie que le bug est produit par une autre interuption pendant l'execution du code mais j'ai vérifié et ca n'est pas le cas..
D'autre part, meme si il existe d'autres plantages etranges, les plus fréquents ont lieu dans une fonction particulière de cette librairie !!
Le jeu de piste dure depuis plusieurs jours deja et je n'en vois pas le bout !
Le bug le plus difficile a trouver sur lequel j'ai jamais travaillé avait lieu quand une interruption non masquable arrivait pendant qu'une autre interruption consommait son maximum de pile et que cette interruption interrompait le programme principal alors qu'il était aussi a son maximum de pile. Alors la pile dépassait de 1 octet sa zone allouée et écrasait des donc des données. Un bon moment après l'interruption le système -- c'était dans un système embarqué programmé totalement en assembleur, il y avait une dizaine de processeurs de 3 modèles diffétents -- partait dans les choux... Il m'a fallu 3 semaines à temps plein pour trouver la source du problème. D'autres y travaillaient depuis des mois (mais à temps partiel). Le problème ne s'est en particulier jamais produit sur une simulation du système qui a tourné pendant tout ce temps.
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
Hello,
Oui, c'est anormal par rapport à la norme. Pour être précis, free(NULL) ne doit rien faire du tout, d'après §7.20.3.2 de la n1124.Envoyé par Médinoc
Maintenant, il a toujours certaines implémentations qui violent la norme sur ce point et qui plantent avec free(NULL), soit pour raisons historiques, soit pour des raisons de débogage. Il faut l'avis des "vieux" pour éclaircir ce point.
A+
Foobar1329
Bon voila ce que j'ai fai pour enregistrer la taille de mes pointeurs. A priori, je ne vois pas de problemes.. Mais j'ai peur des boucles infinies..
J'ai trop relu le code pour voir un eventuel bug.. Est ce que quelqu'un voit un pb dans ce code ?
Si c bon, ca pourra resservir a kkun..
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 typedef struct mesMalloc{ size_t size; void * ptr; struct mesMalloc * pSuivant; struct mesMalloc * pPrecedent; }p_mesMalloc; p_mesMalloc * myFirstMalloc = NULL; p_mesMalloc * rechercheDernierPointeur(void) { p_mesMalloc *pCurrentMalloc = myFirstMalloc; if(pCurrentMalloc == NULL) return NULL; else { while(pCurrentMalloc->pSuivant != NULL) { pCurrentMalloc = pCurrentMalloc->pSuivant; } return pCurrentMalloc; } } p_mesMalloc * recherchePointeur(void * ptr) { p_mesMalloc *pCurrentMalloc = myFirstMalloc; if(pCurrentMalloc == NULL) return NULL; else { while(ptr != pCurrentMalloc->ptr) { if(pCurrentMalloc->pSuivant != NULL) pCurrentMalloc = pCurrentMalloc->pSuivant; else return NULL; } return pCurrentMalloc; } } p_mesMalloc * ajoutNouveauMalloc(void * ptr, size_t size) { p_mesMalloc *pCurrentMalloc = myFirstMalloc; p_mesMalloc *pNewMalloc = NULL; pCurrentMalloc = rechercheDernierPointeur(); if(pCurrentMalloc == NULL) { pCurrentMalloc = (p_mesMalloc *)malloc(sizeof(p_mesMalloc)); if(pCurrentMalloc == NULL) return NULL; pCurrentMalloc->ptr = ptr; pCurrentMalloc->size = size; pCurrentMalloc->pSuivant = NULL; pCurrentMalloc->pPrecedent = NULL; myFirstMalloc = pCurrentMalloc; return pCurrentMalloc; } else { pNewMalloc = (p_mesMalloc *)malloc(sizeof(p_mesMalloc)); pNewMalloc->ptr = ptr; pNewMalloc->size = size; pNewMalloc->pSuivant = NULL; pNewMalloc->pPrecedent = pCurrentMalloc; pCurrentMalloc->pSuivant = pNewMalloc; return pNewMalloc; } } int suppressionMalloc(void * ptr) { p_mesMalloc *pCurrentMalloc = myFirstMalloc; pCurrentMalloc = recherchePointeur(ptr); if(pCurrentMalloc == NULL) return 0; else { if(pCurrentMalloc->pSuivant != NULL && pCurrentMalloc->pPrecedent != NULL) { pCurrentMalloc->pPrecedent->pSuivant = pCurrentMalloc->pSuivant; pCurrentMalloc->pSuivant->pPrecedent = pCurrentMalloc->pPrecedent; } else if(pCurrentMalloc->pSuivant != NULL && pCurrentMalloc->pPrecedent == NULL) { pCurrentMalloc->pSuivant->pPrecedent = NULL; myFirstMalloc = pCurrentMalloc->pSuivant; } else if(pCurrentMalloc->pSuivant == NULL && pCurrentMalloc->pPrecedent != NULL) { pCurrentMalloc->pPrecedent->pSuivant = NULL; } else if(pCurrentMalloc->pSuivant == NULL && pCurrentMalloc->pPrecedent == NULL) { myFirstMalloc = NULL; } free(pCurrentMalloc); return 1; } } int modificationMalloc(void * ptr, size_t size) { p_mesMalloc *pCurrentMalloc = NULL; pCurrentMalloc = recherchePointeur(ptr); if(pCurrentMalloc != NULL) { pCurrentMalloc->ptr = ptr; pCurrentMalloc->size = size; return 1; } else return 0; } int calculTailleMemoireAllouee(void) { p_mesMalloc *pCurrentMalloc = myFirstMalloc; int tailleTotale = 0; while(pCurrentMalloc != NULL) { tailleTotale += pCurrentMalloc->size; pCurrentMalloc = pCurrentMalloc->pSuivant; } printf("taille utilisee = %d\n", tailleTotale); return tailleTotale; }
Ca, ce n'était pas nécessaire . Disons que tu voulais dire 'la taille des objets pointés'.Envoyé par gdpasmini
J'ai déterminé que les points d'entrée étaient :A priori, je ne vois pas de problemes.. Mais j'ai peur des boucles infinies..
J'ai trop relu le code pour voir un eventuel bug.. Est ce que quelqu'un voit un pb dans ce code ?
Ca s'utilise comme ça ? :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 p_mesMalloc *ajoutNouveauMalloc (void *ptr, size_t size); int suppressionMalloc (void *ptr); int modificationMalloc (void *ptr, size_t size); size_t calculTailleMemoireAllouee (void);
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
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
38
39
40 #include <assert.h> #include <string.h> #define PERR(e)\ do\ {\ if (e)\ {\ printf ("ERR %d at %s:%d\n", e, __FILE__, __LINE__); \ }\ }\ while (0) int main (void) { char s[20]; p_mesMalloc *p = ajoutNouveauMalloc (s, sizeof s); if (p != NULL) { printf ("Taille allouee = %lu\n", (unsigned long) calculTailleMemoireAllouee ()); assert (p->ptr != NULL); strcpy (p->ptr, "Hello world"); printf ("%s\n", (char *) p->ptr); { int err = suppressionMalloc (p); PERR (err); } } return 0; }
Pas de Wi-Fi à la maison : CPL
en fait, moi je pensais l'utiliser directement dans mes propre malloc..
Ainsi a chaque malloc appelé, une nouvelle structure est céée contenant le ptr ainsi que sa taille.
Lors d'un free, la structure est detruite et lors d'un realloc, on modifie la taille et le pointeur.
Ceci permet de connaitre a tout moment la taille allouée par malloc.. en enlevant la taille allouée a chaque structures bien sur..
Ainsi on a egalement acces a la taille allouée a un pointeur particulier.. Ce qui peut servir pour un realloc..
Tu as observé des bugs ? Qu'est ce que tu penses de mon code ?
Apparemment, non. Si j'ai bien compris, tu es en train de faire un traceur de mémoire allouée.Envoyé par gdpasmini
Mais ce qui me heurte, c'est que tu utilises 2 concepts que je trouve choquants :
- la mémoire allouée (il y a un coté 'juge et partie' ou 'récursif' qui ne me plait pas (un instrument de mesure ne doit pas influencer la mesure).
- une liste doublement chainée qui est loin d'être triviale, même si on peut espérer qu'elle s'inspire de code déjà validé.
J'ai moi-même construit un 'traceur de mémoire dynamique' qui est basé sur 2 principes différents :
- une zone de stockage statique fournie par l'application
- le formatage en 'tableau' de cette zone de stockage
- l'utilisation d'apparence standard des fonctions du C. C'est une macro qui redirige les fonctions malloc/free vers les miennes (sys_malloc/sys_mem_free). Le code initial est donc inchangé, la seul contrainte est d'inclure "ed/inc/sysalloc.h" en première ligne de chaque source utilisant malloc/free.
http://emmanuel-delahaye.developpez.com/clib.htm
Module SYSALLOC
Pas de Wi-Fi à la maison : CPL
oui je comprends ce que tu veux dire pour le test..
Pour le code, je ne me suis inspiré de rien.. Dou le risque d'erreur.
Sinon pour ton code, c pas mal mais je sais pas si c tres implémentable dans mon system..
D'autant plus que je suis parti pour faire des malloc et des free un peu spéciaux me permettant de reserver une zone memoire en debut d'application et de faire les malloc uniquement dedans...
C'est très portable et je l'ai utilisé à mort en embarqué (réseaux numériques) où il m'a sauvé la vie plus d'une fois...Envoyé par gdpasmini
Oui, un pool. J'ai aussi utilisé ce module dans ce genre de situation. J'ai juste modifié les 4 appels de fonction réels (malloc/calloc/realloc/free) en fonction des appels systèmes requis.D'autant plus que je suis parti pour faire des malloc et des free un peu spéciaux me permettant de reserver une zone memoire en debut d'application et de faire les malloc uniquement dedans...
Ca m'a aussi sauvé la vie et celle de nos partenaires sur ce coup là. (Quoique je ne sais pas si la SAT existe encore...)
Pas de Wi-Fi à la maison : CPL
Alors merci mille fois !
Je vais y jeter oeil mais j'avoue que a premiere vue, ca me semble costaud !
Pour tout dire, je suis debutant et je galere un peu ! lol
Je vais regarder ca de plus pres en essayant de ne pas y passer le we ! Si ca ta sauvé la vie, ca sauvera pe la mienne !
Par contre une quesiton, ce code te permet de créer un pool ou il faut l'impémenter en plus ?
Ca fait 2 questions, donc : non, oui.Envoyé par gdpasmini
C'est uniquement un traceur de mémoire dynamique. C'est à toi d'écrire le pool, mais est-ce bien nécessaire ? Sur tous les systèmes embarqués où j'avais un malloc()/free() opérationnel, je n'ai jamais eu besoin de pool.
Pas de Wi-Fi à la maison : CPL
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager