Alléger un programme pour éviter de faire exploser la pile. - C - Programmation
Marsh Posté le 28-06-2006 à 19:26:55
char host[2000];
passe en malloc ça
char head_buf[10000];
char data_buf[50000];
char enc_buf[5000];
ça
/* Basic Auth info. */
char token_buf[500];
char buf[5000];
et ne fais aucune récursion (si tu en as)
static char b64_encode_table[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 0-7 */
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 8-15 */
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 16-23 */
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 24-31 */
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 32-39 */
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 40-47 */
'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 48-55 */
'4', '5', '6', '7', '8', '9', '+', '/' /* 56-63 */
};
static int b64_decode_table[256] = {
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */
52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */
15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */
-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */
41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */
};
la tu peux rajouter des jolis const
Marsh Posté le 29-06-2006 à 15:34:25
Taz a écrit : char host[2000]; |
Ok ca je suis en train de le faire mais ca plante sur les :
char head_buf[10000];
char data_buf[50000];
char enc_buf[5000];
Taz a écrit : |
Comment çà, je comprend pas ?
Taz a écrit : t'as pas de main au fait ... |
Ouais c'est normal, c'est pas le prog principale mais un fichier comportant des fonctions qui sont appellées depuis le prog principal.
Marsh Posté le 29-06-2006 à 15:42:33
Vilo5 a écrit : Ok ca je suis en train de le faire mais ca plante sur les : |
Ben oui mais non, Taz te dis d'utiliser malloc, ca enlvera tes tableaux de la pile, où ils sont placés si tu les instancies de ta manière.
Vilo5 a écrit : |
Avec const, tes tableaux ne seront plus placés dans la pile.
Marsh Posté le 29-06-2006 à 16:15:26
mais ils ne sont pas sur la pile, ils sont 'static'. le const est quand meme requis si ces tables ne sont pas modifiées
Marsh Posté le 29-06-2006 à 16:48:21
skelter a écrit : mais ils ne sont pas sur la pile, ils sont 'static'. le const est quand meme requis si ces tables ne sont pas modifiées |
Ok.
Enfin bon je suppose que c'est ma pile qui explose, c'est peut être autre chose mais je ne vois pas quoi.
En tout cas sur ma machine de développement ca marche mais pas sur la cible.
Par contre si je fais un bête programme comme le suivant pour appeller mes fonctions post alors ca marche :
Code :
|
C''set donc bien en en reliant les fonctions post à mon prog principal (qui est bien plus gros que celui ci-dessus) que ca explose.
Biensure le prog principal fonctionne si je met en commentaire la ligne d'appel de la fonction post.
Marsh Posté le 29-06-2006 à 20:06:42
Vilo5 a écrit : Ok. |
renseigne toi sur le materiel cible, si le tas et la pile se partagent le meme segment dans la memoire flash alors le fait d'allouer dynamiquement pourrais ne rien changer, c'est peut etre un probleme de consommation de memoire
Marsh Posté le 29-06-2006 à 22:47:05
skelter a écrit : renseigne toi sur le materiel cible, si le tas et la pile se partagent le meme segment dans la memoire flash |
Absurdité. Les données ne sont pas en flash mais en RAM !
Marsh Posté le 30-06-2006 à 00:16:04
Emmanuel Delahaye a écrit : Absurdité. Les données ne sont pas en flash mais en RAM ! |
parce-que un engin ne peut pas avoir de memoire flash qui fait office de ram ??
Marsh Posté le 30-06-2006 à 09:01:06
skelter a écrit : parce-que un engin ne peut pas avoir de memoire flash qui fait office de ram ?? |
Non. Le cycle d'écriture dans la Flash est assez complexe (et son nombre est limité), ce qui interdit ce genre de pratique douteuse. Par contre, c'est OK pour sauvegarder des données non volatiles. (config, log, traces ...).
Sur les systèmes sans disque dur embarquant GNU/Linux, une partie de la Flash est en fait un 'disque Flash' qui contient la partie non volatile du FS (File System) indispensable au fonctionnement de tout Unixoïde...
Marsh Posté le 30-06-2006 à 09:03:23
J'ai de la falsh (2mo) et de la ram (8mo).
Pour plus de détail sur mon module voir : http://www.digi.com/fr/products/em [...] nectme.jsp
Marsh Posté le 01-07-2006 à 06:00:28
skelter a écrit : parce-que un engin ne peut pas avoir de memoire flash qui fait office de ram ?? |
Non. D'ailleurs si tu faisais ça, ta Flash serait morte en quelques jours/heures.
Marsh Posté le 01-07-2006 à 06:12:48
Vilo5 a écrit : Ok. |
En tout cas, une fois que tu as fait ce que t'a dit Taz, ce =n'est plus ce code qui pose pb, c'est le reste (ton main), où tu as dû mettre qqs gros tableaux supplémentaires sur la pile. Si tu te définis comme règle empirique de tjrs faire un malloc au-delà de 128 octets (par ex.), tu ne devrais pas avoir trop de pb. Si 'as besoin de perfs dans une fonction appelée souvent et que tu ne veux pas faire de malloc/free répétés, alors tu crées un buffer de taille fixe sur lequel tu vas travailler et tu passes un pointeur à ta fonction dessus. Evidemment, il faudra un peu plus de rigueur sachant que le buffer n'est pas effacé à chaque utilisation.
cad au lieu de
Code :
|
tu fais :
Code :
|
Conceptuellement, c'est moins joli, mais c'est de l'embarqué...
Marsh Posté le 01-07-2006 à 10:05:46
el muchacho a écrit : Non. D'ailleurs si tu faisais ça, ta Flash serait morte en quelques jours/heures. |
+1, le nombre de lecture/écrite est limité.
Marsh Posté le 01-07-2006 à 11:31:03
el muchacho a écrit : En tout cas, une fois que tu as fait ce que t'a dit Taz, ce =n'est plus ce code qui pose pb, c'est le reste (ton main), où tu as dû mettre qqs gros tableaux supplémentaires sur la pile. Si tu te définis comme règle empirique de tjrs faire un malloc au-delà de 128 octets (par ex.), tu ne devrais pas avoir trop de pb. Si 'as besoin de perfs dans une fonction appelée souvent et que tu ne veux pas faire de malloc/free répétés, alors tu crées un buffer de taille fixe sur lequel tu vas travailler et tu passes un pointeur à ta fonction dessus. Evidemment, il faudra un peu plus de rigueur sachant que le buffer n'est pas effacé à chaque utilisation.
|
Ok c'est noté, merci !
Pour ce qui est de ce que taz a dit j'ai diminué la taille des tableaux qui était surdimensionné, j'ai déclaré en malloc et j'ai fais des free.
Mais par contre je n'ai pas pu le faire pour tous les tableaux.
En l'occurence pour :
char head_buf[10000];
char data_buf[50000];
char enc_buf[5000];
Si je le fait pour ces 3 tableaux mon code plante.
char* head_buf = (char*) malloc(500);
char* data_buf = (char*) malloc(500);
char* enc_buf= (char*) malloc(100);
Apparement en déclarant d ecette façon mon code n'est plus adapté.
Que faut t'il que je change d'autre ?
Marsh Posté le 01-07-2006 à 12:28:05
ReplyMarsh Posté le 02-07-2006 à 01:30:02
Taz a écrit : ueh parce que 10000 != 500 peut-être ? |
Non non ca vient pas de là, la taille du tableau était réellement surdimensionné pour ce que j'en fait.
Avec "char data_buf[500];" ca marche, mais pas avec "char* data_buf = (char*) malloc(500);".
Marsh Posté le 03-07-2006 à 08:56:23
Taz a écrit : et le retour de malloc |
Non pas de pb à ce niveau là.
Apparement ca viendrai plutôt de là :
Code :
|
Dns l'ancien code data_buf était un tableau et sizeof donnait la taille du tableau . Maintenant, data_buf est un pointeur et sizeof renvoie la taille du pointeur, pas la taille du tableau pointé!
Faut donc que je modifie çà je pense, mais comment ?
Marsh Posté le 03-07-2006 à 09:06:50
Vilo5 a écrit : Non pas de pb à ce niveau là.
|
Je te conseille de conserver la taille (ou le nombre d'élements, c'est plus utile) et l'adresse du bloc alloué dans une structure :
Code :
|
Code :
|
Ensuite :
Code :
|
Marsh Posté le 04-07-2006 à 08:47:00
Emmanuel Delahaye a écrit :
|
Ok merci, effectivement ca marche comme ca !
Mais j'aurai tout de même une question a ce sujet pour mieux comprendre.
Comment ca se passe la réservation mémoire dans ce cas ? (ligne par ligne)
Cette déclération réserve t'elle réellement moins de place en mémoire, comment ca se comporte et est-ce bien pour mon pb en embarqué.
Marsh Posté le 04-07-2006 à 10:08:24
Vilo5 a écrit : Ok merci, effectivement ca marche comme ca ! |
C'est surtout que la mémoire n'est pas prise dans la pile, mais dans le tas. Si il n'y en a plus, tu es prévenu (NULL).
Evidemment, il faut libérer après usage.
(Pas trop vite, attention. L'émission se fait mode synchrone ou asynchrone)
Marsh Posté le 04-07-2006 à 13:36:49
Emmanuel Delahaye a écrit : C'est surtout que la mémoire n'est pas prise dans la pile, mais dans le tas. Si il n'y en a plus, tu es prévenu (NULL). |
Pourrait tu exactement m'expliquer la notion de pile et de tas, je pense que ca reste encore un peu plou dans mon esprit.
Je sais que que je charge mon system (busybox) compresser en .bin (environ 1.5Mo) grace a NFS dans mes 2 Mo de flash. Au boot du system je suppose qu'il doit se décompresser dans mes 8Mo de ram. Après je suppose que quelque part dans la ram je doit avoir la pile pour mes applications, et le reste serait le tas. Ou rien à voir ?
Marsh Posté le 04-07-2006 à 13:56:46
Vilo5 a écrit : Pourrait tu exactement m'expliquer la notion de pile et de tas, je pense que ca reste encore un peu plou dans mon esprit. |
C'est à peu près çà, oui. Le tas, c'est la mémoire n'est occupée ni par le code, ni par les données (données statiques), ni par la pile (données automatiques). C'est dans cette zone que l'allocateur de mémoire dynamique vient reserver/libérer des blocs de données (malloc() / free()).
Marsh Posté le 04-07-2006 à 15:05:15
Emmanuel Delahaye a écrit : C'est à peu près çà, oui. Le tas, c'est la mémoire n'est occupée ni par le code, ni par les données (données statiques), ni par la pile (données automatiques). C'est dans cette zone que l'allocateur de mémoire dynamique vient reserver/libérer des blocs de données (malloc() / free()). |
Ok !
Et la pile est bien dans la ram aussi ? Mais elle, elle prend une taille qui est réservé et situé a un endroit bien précis dans la ram. Et c'est cette taille qu'il ne faut pas dépasser sous risque de faire exploser la pile et avoir un programme qui se comporte n'importe comment et plante. Donc en règle général faut faire de mallocs et free au maximum car le tas est normalement plus grand que la pile, même dans l'embarqué.
Marsh Posté le 04-07-2006 à 15:10:33
Bon alors voilà j'ai changé pas mal de chose dans le code, j'ai changé les déclaration pour mettre des mallocs suivi de free biensur, j'ai ajouté les structure que emmanuel ma conseillé et j'ai aussi ajouté du code pour récupérer juste les données que je souhaite et non tout le code XML provenant du serveur.
Voici mon nouveau fichier :
Nouveau fichier
J'ai mis en commentaire les lignes que j'ai changé (// en début de ligne qui se repère facilement), pourriez vous me dire si cela vous parrait correct et si j'ai bien fait des test correct sur mes mallocs et placé correctement mes free.
merci
Marsh Posté le 04-07-2006 à 16:51:41
ReplyMarsh Posté le 04-07-2006 à 17:20:21
Taz a écrit : et le saint esprit l'a transformé en C++ ? |
Ok ok mauvais rename lors du copier/coller, sorry !
Nouveau fichier
Marsh Posté le 04-07-2006 à 17:25:11
1) t'as pas aimé ma remarque sur les const
2) je pense que les malloc n'ont servi à rien, c'était juste tes char[500000] qui foutaient la merde.
Marsh Posté le 04-07-2006 à 17:35:26
Code :
|
Marsh Posté le 05-07-2006 à 08:59:22
Taz a écrit : 1) t'as pas aimé ma remarque sur les const |
Ok ok j'y penser plus à ça, donc toi tu veirrai bien ca :
Code :
|
Comme ca les tableaux ne seront plus dans la pile.
Taz a écrit : 2) je pense que les malloc n'ont servi à rien, c'était juste tes char[500000] qui foutaient la merde. |
Bon ok de toute façon j'ai réduit les tableaux (ce que tu dit qui est bien) et en plus j'ai mis les malloc. Ca peut pas faire de mal d'avoir fait les 2 je pense, plutôt que du bien car je décharge tout de même un peu la pile comme çà. Car si ma pile et vraiment petite (2 ou ko par exemple, j'attend une réponse d emon fournisseur pour être fixé), elle se rempira vite.
Marsh Posté le 05-07-2006 à 10:18:57
Taz a écrit :
|
???????
Désolé, mais je n'ai pas tout compris ce que tu essaye de me dire là ?
Marsh Posté le 05-07-2006 à 10:47:32
Ce qu'il veut dire c'est que ton code dénote une certaine méconnaissance du langage C, assez inquiétante étant donné ce que tu essaies de faire...
Dans l'ordre:
|
Si tu ne vérifie pas la valeur de retour de write, comment peux-tu savoir que ça c'est bien passé, surtout que quand tu bosses avec des sockets, il est tout à fait possible qu'un seul appel ne suffise pas.
NEsuite,
|
As-tu entendu parler d'une règle qui dit que dans une expression (à quelques exceptions près), un tableau est "considéré" (decay en anglais, je ne trouve pas l'équivalent en français) comme unpointeur vers son premier élément? Donc ton expression est strictement équivalente à 'eq'.
Enfin,
|
Là c'est carrément louche.
En jettant un coup d'oeil à ton code, on voit que tu castes tes malloc() à chqaue fois, ensuite tu testes la valeur de retour.
Pourquoi ne pas factoriser le code en un xmalloc, histoire de gagner 50 lignes de codes.
En bref, si ton programme plante, c'est sûrement parce qu'il est mal codé.
Marsh Posté le 05-07-2006 à 11:09:02
tu veux pas sortir un bouquin, lire wikipedia ou pire lire ce sujet en entier
Citation : Comme ca les tableaux ne seront plus dans la pile. |
je ne sais pas trop ce qu'on cherche en fait avec toi vu que tu ne sais pas ce qu'est la pile.
Marsh Posté le 05-07-2006 à 11:15:28
[Hors Sujet]J'ai une question sur tes 'coding rules': je trouve que les 'exit' dans des fonctions auxiliaires est une pratique très violente dans l'embarqué, ton main est mort sans savoir vraiment pourquoi... n'est-il pas plus judicieux de retourner une valeur signifiant 'error' pour que le main puisse retomber sur ces pieds? De plus, avant les 'exit' dans les cas de mauvais malloc, tu ne libère pas la mémoire précedement allouée...
Globalement, ton code me fait peur
Marsh Posté le 05-07-2006 à 11:16:13
Bon ok,
alors de toute façon les lignes suivantes :
Code :
|
Puisque tout ce que je veux c'est récupérer "data.data" qui est ma réponse XML, afin de la traiter (enlever les balises XML pour récupérer juste le nom et le solde)
Marsh Posté le 05-07-2006 à 13:24:33
western a écrit : [Hors Sujet]J'ai une question sur tes 'coding rules': je trouve que les 'exit' dans des fonctions auxiliaires est une pratique très violente dans l'embarqué, ton main est mort sans savoir vraiment pourquoi... n'est-il pas plus judicieux de retourner une valeur signifiant 'error' pour que le main puisse retomber sur ces pieds? De plus, avant les 'exit' dans les cas de mauvais malloc, tu ne libère pas la mémoire précedement allouée... |
Oui c'est vrai c'est a modifier aussi, il faudra que je regarde ca aussi après, mais la pour le moment je m'acharne à esayer de la faire tourner sur ma platform embarqué. mais ce n'est pas a négliger je suis d'accord faudra que je traite çà.
En fait le pb principal, vous vous en douté, c'est que à la base ce n'est pas un programme codé pour de l'embarqué. Ca se voit d'ailleurs !
Marsh Posté le 05-07-2006 à 14:23:10
Je ne vois pas ce que tu peux de faire plus dans ce fichier (à part faire des write directe au lieu de sprintf et concatenation) mais tu risque de sérieusement dégradé les performances
question: Que fait le main? Combien de RAM utilise-t-il? Peux-tu l'optimiser? Tu peux utiliser des outils comme gprof et gcov et biensur gdb/ddd pour regarder la mémoire, les appels aux fonctions, etc.
Marsh Posté le 28-06-2006 à 17:32:55
Bonjour,
Je dévelloppe actuellement des apllis sous linux destiné à une cible embarqué de très faible taille (mémoire(2Mo flash), proc (55Mhz),...).
Mon problème est que l'appli sur laquel je travaille actuellement fait apparement explosé la pile de ma cible, alors qu'elle marche sans aucun pb sur ma machine de dévelloppement.
J'aimerais avoir vos suggestions pour pouvoir réduire la taille qu'occuppe mon programme dans la pile.
En fait j'ai un prog principal qui tourne mais quand je lui rajoute une fonction supplémentaire (fonction de post) qui se trouve dans un fichier à part, alors ca plante. Cette fonction fonctionne correctement sur ma cible lorsque je me contente de l'appeller depuis un simple programme de 2 lignes.
je vous met sur ftp le fichier concerné en espérent que vous m'aidiez a réduire l'occupation de se programme.
Lien : fichier
Merci d'avance
Message édité par Vilo5 le 28-06-2006 à 17:33:52