Pb de malloc : ça marche , mais ça marche pas ... :-( - C - Programmation
Marsh Posté le 24-12-2003 à 03:53:49
Use the source Luke!
A+,
Marsh Posté le 24-12-2003 à 09:04:56
ça serait bien que tu nous files le source, si tu veux qu'on t'aide ça sera plus pratique...
mais vu ce que tu nous dis:
- allocation du tableau dans une fonction -> plantage
- allocation du tableau toute seule dans 1 prog. -> ça marche
moi je voterais pour un problème lors de passage de paramètres à ta fonction (genre tu passes directement le pointeur sur ton tableau au lieu de l'adresse de celui-ci...)
Mais bon, file les sources, on n'a pas assez d'infos là
Marsh Posté le 24-12-2003 à 10:22:08
utilisation d'un vérificateur de fuites de mémoire (je pense à valgrind et Co) peut aider...
Marsh Posté le 24-12-2003 à 11:54:30
western a écrit : utilisation d'un vérificateur de fuites de mémoire (je pense à valgrind et Co) peut aider... |
j'ai dans l'idée que c'est sortir l'artillerie lourde pour un bete pb de pointeur
Marsh Posté le 24-12-2003 à 16:44:25
voici mon code source . rien de tres faramineux.
le premier printf("@\n" ); s'affiche , pas le second.
les parametres sont bien rentrés , merci chrisbk ;D . d'ailleurs j'ai inseré un "printf ("%d , %d \n ", n , m );" qui me confirme que les valeurs sont bonnes .
ce qui est marrant ,c'est que si je fais une boucle for avant la premiere existante ,et que je demande , par exemple d'afficher l'adresse des int_char deja alloué (ce qui n'a aucun interet pour moi , mais c'est juste pour voir si ils sont accessibles), et bien dans la boucle qui plante ,ça plante une iteration avant .
par , mes deux parametre sont n=12 et m=7 . et la boucle plantera a la valeur de i=7 au lieu de planter a la valeur de i=8 ;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
typedef struct int_char{
int x;
char c;
}int_char;
int_char** allouer_memoire_a_un_tableau ( int n, int m ){
int i, j ;
int_char ** tab ;
printf ("%d , %d \n ", n , m );
if(!n || !m) printf("erreur dans la fonction :char** allouer_memoire_a_un_tableau : tableau sans dimension" );
tab = malloc(sizeof(int_char*)*n);
printf("@\n" );//ça c pour voir où ça blok lors de l'execution
for (i=0; i<= n ;i++){
tab[i] = malloc(sizeof(int_char)*m);
}
printf("@\n" );
for (i=0; i<= n ;i++){
for (j=0;j<= m ;j++){
tab[i][j].c='.';
}
}
if (!tab) printf("erreur tab est vide \n" );
return tab;
}
int main(){
int_char**tab;
tab=allouer_memoire_a_un_tableau( 12, 7);
return 0;
}
un verrificateur de fuite de mémoire j'imagine que c'est pas facil d'acces ?je me trompe ? y a pas un parametre qui pourrait créer cette merdouille ?
Marsh Posté le 24-12-2003 à 16:53:11
Plantage dans malloc =
- Soit tu recopies le resultat dans une zone mémoire incorrecte ( et donc ce n'est pas vraiment un plantage dans malloc )
- Soit tu corromps allegrement les données de malloc. Double free, lecture/ecriture dans la zone mémoire juste avant un pointer retourné par malloc. En général, le resultat se fait sentir quelques allocations plus tard.
Comclusion : utilise un truc comme Valgrind ou Purify
PS : ta bloucle for va une case trop loin : il faut tester i < strict a n, pas inferieur ou egal.
PPS : utilise les balises "[cpp]" pour faire passer ton post de "bouillie infame" a "code lisible" même pour des gens n'utilisant pas un navigateur en mode texte.
Marsh Posté le 24-12-2003 à 18:43:57
Il doit y avoir un problème de principe : je crois avoir vu qu'il fallait plutôt déclarer le **tab dans le main (ce qui est fait) mais passer son adresse en argument lors de l'appel à la fonction. Ca évite que la mémoire allouée dans
int_char** allouer_memoire_a_un_tableau ( int n, int m ){
int i, j ;
int_char ** tab ; etc..
ne disparaisse dès qu'on sort de la fonction (selon le bon vouloir du compilo qui optimise ce qui ne sert plus avec un grand coup de balai, on égalise un pointeur avec un fantôme).
Genre
allouer_memoire_a_un_tableau ( int n, int m, int_char **tab ){
Pour les dimensions, les indices commençant à 0, si on a n cases, on fait boucle i = 0; i < n; i ++ (idem pour les accès après allocation).
Marsh Posté le 24-12-2003 à 19:43:25
Le probleme, c'est que Aloo n'a pas bien compris son cour de C en ce qui concerne les indices des tableaux:
s' il fait
tab = malloc(sizeof(int_char*)*n);
il alloue une zone memoire que l' on peut assimiler a un tableau a n cases, et donc qu' on pourra adresser avec un indice variant de 0 a n-1.
La boucle suivante:
for (i=0; i<= n ;i++){
tab[i] = malloc(sizeof(int_char)*m);
}
deborde donc d' un cran quand i vaut n, et ca creera des problemes.
Donc il faut corriger les 2 endroits ou les boucles sont erronées et ca devrait rentrer dans l'ordre.
A+,
Marsh Posté le 24-12-2003 à 19:49:32
Mauvaise langue gillou , c'est que mon tableau je le veut d'une case en plus . parceque sur la premire ligne et la premiere colone je remplie des indices que je veut comme ça . et lorsque je fais une boucle apres c'est plus simple parceque mon indice n correspond donc a la nieme case du tableau , et non plus a la n-1 ieme ...
pour carbone 14 j'ai essayé de faire comme tu dis ; c a dire que j'ai effacer ma fonction allouer_tableau et je l'ai inserer en la modiffiant un peu , directement dans la fonction qui l'appelait .. ça ne marche pas mieux ... .
je ne pense pas revnir avt demain ,alors joyeux noel a tous et merci de vos reponses.
Marsh Posté le 24-12-2003 à 20:38:40
Aloo a écrit : Mauvaise langue gillou , c'est que mon tableau je le veut d'une case en plus . parceque sur la premire ligne et la premiere colone je remplie des indices que je veut comme ça . et lorsque je fais une boucle apres c'est plus simple parceque mon indice n correspond donc a la nieme case du tableau , et non plus a la n-1 ieme ... |
Quelles que soit la taille que tu veuille donner à ton tableau, il faut que tu alloues assez de mémoire pour le contenir ! S'il va de l'indice 0 à l'indice n inclus, sa taille totale est (n+1) et donc ton malloc et faux.
Marsh Posté le 24-12-2003 à 21:26:21
Aloo a écrit : Mauvaise langue gillou , c'est que mon tableau je le veut d'une case en plus . parceque sur la premire ligne et la premiere colone je remplie des indices que je veut comme ça . et lorsque je fais une boucle apres c'est plus simple parceque mon indice n correspond donc a la nieme case du tableau , et non plus a la n-1 ieme ... |
Ben dans ce cas la, si tu veux que ton tableau fasse une case de plus, il faut l'allouer, cette case de plus!
tab = malloc(sizeof(int_char*)*(n+1));
A+,
Marsh Posté le 26-12-2003 à 16:26:27
Aloo a écrit : ok ok , mais c'est pas le pb |
Si justement.
Marsh Posté le 26-12-2003 à 18:05:57
bé non ... si y avait un pb ac la taille du tableau , genre une cellule en plus ou en moins il plantrait au moment où il utiliserait cette cellule . dans une boucle qui va de 0 a 12 il plante a la 8 case (ou la 7eime lorsque je fait une boucle afficher ) avant .
et non c'est pas ça le pb , parceque dans mon envoie de parametre et tout ça je m'y retrouve (<n+1 = <=n ) .
Marsh Posté le 26-12-2003 à 19:21:33
Aloo a écrit : bé non ... si y avait un pb ac la taille du tableau , genre une cellule en plus ou en moins il plantrait au moment où il utiliserait cette cellule . dans une boucle qui va de 0 a 12 il plante a la 8 case (ou la 7eime lorsque je fait une boucle afficher ) avant . |
Quand tu lis ou ecrit dans une zone mémoire non alloué, c'est du UB : Undefined Behaviour. Autant que tu saches, ton ordi pourrait commencer à te faire le café. Corrige déjà ça et après on n'en reparle.
PS : ton programme marche très bien avec gcc, mais par contre, Valgrind guelle comme c'est pas permis sur tes depasements mémoire bien sur. A part ça, il n'y a pas l'air d'avoir de problèmes.
Marsh Posté le 26-12-2003 à 19:27:57
On peut des fois accéder à des endroits où on a écrit sans en avoir le droit (genre débordement), ça marche des fois et d'autres fois plus du tout selon sur quoi on "marche"/écrase.
Dans
int main()
{
int_char**tab;
tab=allouer_memoire_a_un_tableau( 12, 7);
return 0;
}
en remplaçant la fonction par son contenu, ça fonctionne, ou ça cafouille aussi ? (avec malloc (* (n + 1) et ( * (m + 1)
Marsh Posté le 26-12-2003 à 20:07:45
carbon_14 a écrit : On peut des fois accéder à des endroits où on a écrit sans en avoir le droit (genre débordement), ça marche des fois et d'autres fois plus du tout selon sur quoi on "marche"/écrase. |
En tout cas sous VC++, avec des index corrects (de 0 a n-1 et m-1), ca passait sans pb. Et pareil avec des mallocs bien faits.
A+,
Marsh Posté le 26-12-2003 à 20:14:44
taz a écrit : c'est quoi ces conneries d'indexer sur [0;n] ? |
Au fait tu avais vu mon cadeau de noel (mis dans blabla@prog)??
Code :
|
A+,
Marsh Posté le 26-12-2003 à 22:40:11
Bon , dans le doute , j'ai clarrifier mon programme (cad que tout est bien claire , quand je dit allouer memoire (n,m) ça alloue donc n*m cases et non pas (n+1)*(m+1), meme si le pb n'etait pas la et je n'ecris pas sur une zone non allouée .
lorsque j"execute a part cette fonction elle marche tres bien et ne pose aucun pb . ce n'est que dans le programme qu'elle deconne . ..
d'ailleurs c'est marrant , parcequ'avant j'avais la meme fonction et je trvaillais que ac des char , donc n'allouais que des char . et ça marchait tres bien ! mais par la suite j'ai u besoin d'un int et d'un char et j'ai donc créé une structure ac les deux .et pis la du coup ça plante .
Marsh Posté le 26-12-2003 à 23:15:16
Si ca plante quand y'a du code supplementaire, c'est que ton pb est dans le code supplementaire.
A+,
Marsh Posté le 27-12-2003 à 12:52:55
ouai , mais le code supplementaire s'execute sans pb . et du coup je sais pas où peut se trouver l'erreur je sens que ça va etre galere cette histoire .
Marsh Posté le 27-12-2003 à 14:30:09
T'es lourd à force : pourquoi t'essaie pas déjà de corriger les pbs de dépassement mémoire que tout le monde t'a signalé ???
Aloo a écrit : bé non ... si y avait un pb ac la taille du tableau , genre une cellule en plus ou en moins il plantrait au moment où il utiliserait cette cellule . dans une boucle qui va de 0 a 12 il plante a la 8 case (ou la 7eime lorsque je fait une boucle afficher ) avant . |
Si tu parles bien de cette boucle-là, tu as un dépassement mémoire :
Code :
|
n=12 et m=7
Chaque fois que j=7, tu écris dans une case que nous n'as pas allouée donc ça peut expliquer un plantage avant la dernière itération.
Marsh Posté le 27-12-2003 à 15:53:14
enidan a écrit : T'es lourd à force : pourquoi t'essaie pas déjà de corriger les pbs de dépassement mémoire que tout le monde t'a signalé ???
|
Ca fait un bail que ca a ete dit...
A+,
Marsh Posté le 27-12-2003 à 15:53:29
c'est fait (d'ailleurs je l'ecris dans le topic du 26 a 22:40). et non c'est pas cette boucle qui foire . et si ça foirait parceque y avait un pb de depassement de mémoire alors c'est la fonction qui serait fausse . or lorsque j'execute cette fontion en dehors du prg elle marche nikel
Marsh Posté le 27-12-2003 à 15:55:04
Aloo a écrit : ouai , mais le code supplementaire s'execute sans pb . et du coup je sais pas où peut se trouver l'erreur je sens que ça va etre galere cette histoire . |
y'a sans doute un probleme dans ce code neanmoins, probleme mis en evidence/declenché par celui que tu nous a montré.
A+,
Marsh Posté le 27-12-2003 à 17:58:13
Aloo a écrit : c'est fait (d'ailleurs je l'ecris dans le topic du 26 a 22:40). et non c'est pas cette boucle qui foire . et si ça foirait parceque y avait un pb de depassement de mémoire alors c'est la fonction qui serait fausse . or lorsque j'execute cette fontion en dehors du prg elle marche nikel |
Dsl, j'avais pas compris que tu avais rectifié.
Tu devrais poster le code corrigé pour qu'on puisse voir ce qui cloche encore.
A+
Marsh Posté le 28-12-2003 à 03:11:37
merci ... mais apparement c'etait pas cette partie de code que j'ai postée qui plantait .. mais bien le reste du code (qui doit approché le millier de ligne , alors je vous l'epargne , et puis vu que je programme comme un cochon (j'ai moi meme du mal a comprendre ce que j'ai ecris parfois )) je ne vous l'inflige pas ...
Alors cette aprem j'ai pris mon courrage a deux main et réecri plus simplement le code deja ecrit . en supprimant des malloc dans tous les sens .. en bas du coup , c'est plus claire et ça marche . Alors bon je vais arreter de vous embetter ..
Mais je suis qd meme curieux sur les effets de bords des printfs ... c'est un drole de fenomene .
Marsh Posté le 28-12-2003 à 10:10:27
On a tous fait ainsi. Reecrire de maniere plus simple, c'est le debut de la maturite en prog.
Plus tard, tu verras la tete de ton chef de projets quand tu lui dit: j'ai reecrit ce morceau, de maniere plus simple (parce que pour lui, ca veut dire que tous les tests validant ce qui fait appel a ce que tu as reecrit sont a recommencer)
A+,
Marsh Posté le 24-12-2003 à 02:41:34
J'en ai marre !
ça devrait marcher mais ça ne marche pas ! et du coup je me ronge tous les ongles !
dans mon programme je cherche a allouer de la memoire a un tableau . pour ça je cré un structure ** a qui j'alloue la hauteur du tableau , puis je fais un strcutre[i]= malloc(sizeof(structure)* la longueur du tableau )) ;
pour i qui parcours la hauteur , evidement .
jusque la rien de fantastique .
j'ai fini mon programme , alors tout fier je le test pour m'amuser , ça marche impec , sauf pour un ex ! je remonte la source du pb et je trouve que la fonction qui alloue de la mémoire au tableau plante .
Pour tester si c ma fonction qui est mal ecrite (ça m'etonnerais je l'ai pompé sur un corrigé d'exo ) je la compile a part et test les valeurs qui font planter mon programme principal . Naturellement la fonction marche correctement et il y a aucun pb ...
Alors du coup je suis sceptique . lorsque je lance la fonction dans un fichier a part tout marche correctement mais quand elle est lancée dans mon programme elle plante ...
Alors je lache pas l'affaire et j'essaye de remonter le plus pres possible du plantage ... et bien c'est assez marrant parceque ça plante sans raison .
je m'explique .
je demande , dans une boucle , a ma fonction qui alloue de la mémoire , de justement en allouer un certain nombre de fois (12 fois en loccurrence) . et il se trouve qu'elle alloue sans probleme les 7 premiers et qu'elle plante au 8eime ... et si par exemple , avant , je lance un boucle pour afficher n'importe quoi , elle plante apres les 6 premieres allocations ...
Alors je comprends plus rien ?
Est ce qu'il y a un nombre maximal de memoire qu'on peut allouer ? dans ce cas je ne pense pas qu'avec moins de 1000 int et 1000 char on fasse exploser la machine ?