IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Ouvrir un fichier en "global"?


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de mikhailo
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    78
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 78
    Par défaut Ouvrir un fichier en "global" / optimisation du temps d'exécution
    Bonjour,

    Voici un autre petit souci que je rencontre. J'ai un programme qui a la structure suivante: le programme principal, et deux modules .h. Un des modules contient une fonction de recherche de mots sur un fichier texte, et le programme principal appelle cette fonction dans une boucle qui se répète beaucoup (très beaucoup) de fois.

    Au bout de environ 10k itérations (ça dépend des ordinateurs), j'ai un segfault.

    La question est: est-il possible que cela provienne du fait que l'on charge en mémoire et referme sans arrêt un fichier (qui fait 40 mégas)? Et si oui, y a-t-il un moyen de déclarer l'ouverture du fichier en question de façon globale, à ce que la fonction de recherche qui se trouve dans le module le voie? (ce qui éviterait donc de l'ouvrir et le refermer des milliers de fois).

  2. #2
    Membre éclairé Avatar de mikhailo
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    78
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 78
    Par défaut
    Eh bien, suffisait que je poste ici après plusieurs jours de désespoir, et quelqu'un m'a aidé à trouver la solution de la chose:



    1° Effectivement, des demandes d'allocation de mémoire en trop grand nombre, que ce soit avec un fopen() ou un malloc() peuvent provoquer un segfault;



    2° Voici comment faire pour éviter cela:

    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
    #include <diverses_libs.h>
     
    // déclaration de variables globales relatives à fonction_annexe()
    FILE* fichier;
    char* ligne_renvoyee;
     
     
     
    char* fonction_annexe(char input[])
    {
    //diverses opérations sur le fichier;
     
    	return ligne_renvoyee;
    }
     
     
     
     
    int main(int argc, char** argv[})
    {
    	char* result;
     
    //affectation des variables relatives à fonction_annexe()
    	fichier = fopen(chemin_du_fichier, "r");
    	ligne_renvoyee = (char*)malloc(200);
     
    	while (true)
    	{
    //opérations diverses
    		result = fonction_annexe(argv[1]);
    	}
    	fclose(fichier);
    	return result;
    }

    Il faut juste penser à placer le curseur au début du fichier à chaque fois, pour qu'à chaque boucle il soit comme si l'on venait de l'ouvrir, avec fseek(fichier, 0, SEEK_SET).

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 484
    Par défaut
    Bonsoir,

    Citation Envoyé par mikhailo Voir le message
    Voici un autre petit souci que je rencontre. J'ai un programme qui a la structure suivante: le programme principal, et deux modules .h. Un des modules contient une fonction de recherche de mots sur un fichier texte, et le programme principal appelle cette fonction dans une boucle qui se répète beaucoup (très beaucoup) de fois.
    Les fichiers « *.h » servent à contenir les prototypes de fonctions (headers), les déclarations de toutes sortes, les macros, etc. mais pas le code ! Si tu veux faire une compilation séparée, il faut utiliser plusieurs fichiers *.c.

    Citation Envoyé par mikhailo Voir le message
    1° Effectivement, des demandes d'allocation de mémoire en trop grand nombre, que ce soit avec un fopen() ou un malloc() peuvent provoquer un segfault;
    Non, pas directement. Appeler trop souvent malloc() ou fopen() peut conduire à épuiser les ressources (ou mettre le système à genoux) et seulement si tu ne les libères pas entretemps. Si les ressources sont épuisées, malloc() et fopen() renvoient NULL si elles ont échoué.

    Si segfault il y a, c'est que soit tu ignores la valeur de retour de ces fonctions, soit le problème ne se trouve pas là où tu le crois.

    2° Voici comment faire pour éviter cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include <diverses_libs.h>
     
    // déclaration de variables globales relatives à fonction_annexe()
    FILE* fichier;
    char* ligne_renvoyee;
    Les variables globales, c'est mal. Surtout si leur seule utilité est de permettre à deux fonctions de communiquer. Tu peux tout-à-fait passer le descripteur « fichier » en argument de ta fonction. En plus, tu n'auras même pas besoin de modifier son code, et tu pourras manipuler plusieurs fichiers à la fois sans avoir besoin de refermer le premier avant (chose qu'il faudra quand même faire si tu ne comptes plus l'utiliser dans un avenir immédiat).

    Il faut juste penser à placer le curseur au début du fichier à chaque fois, pour qu'à chaque boucle il soit comme si l'on venait de l'ouvrir, avec fseek(fichier, 0, SEEK_SET).
    C'est effectivement mieux que de fermer et le rouvrir systématiquement mais, d'une part, on ne voit nullement apparaître cette ligne dans le code que tu nous as donné, les « diverses opérations » ne nous aidant pas à nous faire une idée et, d'autre part, ce n'est sûrement pas cela qui provoque ta segfault. Par contre, il y a une erreur à ce niveau :

    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
    #include <diverses_libs.h>
    
    // déclaration de variables globales relatives à fonction_annexe()
    FILE* fichier;
    char* ligne_renvoyee;
    
    char* fonction_annexe(char input[])
    {
            //diverses opérations sur le fichier;
    	return ligne_renvoyee; // Voir n° 1
    }
    
    int main(int argc, char** argv[})
    {
    	char* result;
    
            //affectation des variables relatives à fonction_annexe()
    	fichier = fopen(chemin_du_fichier, "r");
    	ligne_renvoyee = (char*)malloc(200); // Voir n°2
    
    	while (true)
    	{
                    //opérations diverses
    		result = fonction_annexe(argv[1]); // Voir n°3
    	}
    
    	fclose(fichier);
    	return result; // Voir n° 4
    }
    1. Tu renvoies la valeur d'une variable globale. À quoi cela sert-il ?
    2. Tu alloues 200 octets, mais tu ne les libères jamais !
    3. « result » prendra ici la valeur de la variable globale « ligne_renvoyee », ce qui, encore une fois, ne sert à rien !
    4. Ça c'est absolument faux. Ta fonction main() est de type « int » mais tu renvoies un « char * », ce qui n'a aucun sens. Le pointeur lui-même pointe vers une zone de mémoire allouée par le processus et qui sera donc détruite avec lui. Quelque soit l'entité qui héritera du code de retour de ton processus, elle n'obtiendra rien de valable.


    Tout cela ressemble beaucoup à de mauvaises habitudes héritées de Java. Est-ce le cas ?

    Bonne chance.

  4. #4
    Membre éclairé Avatar de mikhailo
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    78
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 78
    Par défaut
    Bonjour, et merci pour ta réponse détaillée. Je n'ai pas mis le code complet de la chose pensant que ce ne serait pas intéressant pour tout le monde, mais je vais le mettre pour que tu voies mieux la tête du truc:

    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
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
     
     
    #define DICO "lefff-2.1.txt"
    #define TAILLE_LIGNE_MAX 200
     
     
     
    /*Déclaration des variables globales relatives à rechercheDichotomique() */
    FILE* FICHIER_DICO;
    char* LIGNE_RENVOYEE;
     
     
     
     
    /*
    Extrait une partie du mot, comprise entre les indices i et j. On suppose:
    i < j;
    j <= (strlen(mot) - 1);
    */
     
    char* extractPart(char mot[], int i, int j)
    {
    	char* partie = (char*)malloc(TAILLE_LIGNE_MAX * sizeof(char));
    	int k = 0;
     
    	for (k = i; k <= j; k++)
    	{
    		partie[k-i] = mot[k];
    	}
    	return partie;
    }
     
     
     
     
     
     
    /*
    Fonction concaténant en un mot deux mots prix en argument.
    */
    char* concateneMots(char mot1[], char mot2[])
    {
    	char* concatenation = (char*)malloc(TAILLE_LIGNE_MAX * sizeof(char));
     
    	strcpy(concatenation, mot1);
    	strcat(concatenation, mot2);
     
    	return concatenation;
    }
     
     
     
     
     
     
     
     
     
     
     
     
    int nombreLignes(char chemin[])
    {
    	int nombre_lignes = 0;
    	char c[200];
     
    	FILE* fichier = NULL;
    	fichier = fopen(chemin, "r");
     
    	while (fgets(c, TAILLE_LIGNE_MAX, fichier) != NULL)
    	{
    		nombre_lignes++;
    	}
     
    	fclose(fichier);
    	return nombre_lignes;
    }
     
     
     
     
     
     
    /*
    accoutrée		v	[pred='accoutrer_____1<obj:(sn),objde:(de-sn),suj:(par-sn)>',cat=v,@passive,@être,@Kfs]
    */
     
    char* partOfSpeech(char ligne_dico[])
    {
    	char* mot = (char*)malloc(TAILLE_LIGNE_MAX * sizeof(char));
    	int* nombre = (int*)malloc(TAILLE_LIGNE_MAX * sizeof(int));
    	char* classeg = (char*)malloc(TAILLE_LIGNE_MAX * sizeof(char));
    	sscanf(ligne_dico, "%s %d %s", mot, nombre, classeg);
    	if (*nombre == 0)
    	{
    		sscanf(ligne_dico, "%s %s", mot, classeg);
    	}
     
    	return classeg;
    }
     
    /*
    verbe, adjectif, pronom, nom commun, (nom propre), adverbe, *conjonction de coordinations, *préposition
    v	adj	pro		nc	np		adv	coo				prep
    conjonction de subordination,			determinant,
    csu(afin que)			cld(lui)	det
     
    */
     
     
     
     
    /*
    Fonction qui extrait le mot de la ligne du dictionnaire correspondante.
    */
    char* getMot(char ligne_dico[], char mot_recup[])
    {
    	sscanf(ligne_dico, "%s", mot_recup);
    	return mot_recup;
    }
     
     
     
     
     
     
     
     
     
     
    char* rechercheDichotomique(char mot[])
    {
    	int stop = 0;
    	int position_current = 0;
    	int n = 2;
    	int signe = 1;
    	int etape = 0;
    	int modificateur = 0;
    	int k = 0;
    	int l = 0;
    	int leng = 0;
    	char aux[TAILLE_LIGNE_MAX];
    	char mot_lu[TAILLE_LIGNE_MAX];
    	char c[1];
     
    	fseek(FICHIER_DICO, 0, SEEK_END);
    	int taille_dico = ftell(FICHIER_DICO);
    	fseek(FICHIER_DICO, 0, SEEK_SET);
     
    	while (stop != 1)
    	{
    		if (position_current%2 == 0)
    		{
    			modificateur = taille_dico/n;
    		}
    		else
    		{
    			modificateur = ((int)taille_dico/(n)) + 1;
    		}
     
    		if (modificateur < k)
    		{
    			modificateur = k;
    		}
     
    		position_current = position_current + signe*(modificateur);
     
    		if (position_current < 0)
    		{
    			position_current = position_current + modificateur - l;
    		}
     
     
    		etape = etape + 1;
    		n = n * 2;
     
    		fseek(FICHIER_DICO, position_current, SEEK_SET);
    		l = 0;
     
    		while((c[0] = fgetc(FICHIER_DICO)) != '\n')
           		{	
        			fseek(FICHIER_DICO, -2, SEEK_CUR);
    			l = l + 1;
     
    		}
    		position_current = position_current - l;		
     
     
    		fscanf(FICHIER_DICO, "%s", mot_lu);
    		leng = strlen(mot_lu);
    /*
    		printf("etape %d, position dans le fichier: %d, pas de la recherche: %d\n", etape, position_current, modificateur);
    		printf("mot lu: %s\n", mot_lu);
    		printf("comparaison entre %s et '%s': %d\n\n", mot_lu, mot, strcmp(mot_lu, mot));
    */		
    		if (etape > 25)
    		{
    			fseek(FICHIER_DICO, 0, SEEK_SET);
    			return "*error";
    		}
    		if (strcmp(mot_lu, mot) == 1)
    		{
    			signe = -1;
    			k = 24;
    			while ((c[0] = fgetc(FICHIER_DICO)) != '\n')
    			{
    				k = k + 1;
    			}
     
    			fseek(FICHIER_DICO, -k, SEEK_CUR);
     
    		}
    		if (strcmp(mot_lu, mot) == -1)
    		{
    			signe = 1;
    			k = 24;
    			while ((c[0] = fgetc(FICHIER_DICO)) != '\n')
    			{
    				k = k + 1;
    			}
     
    			fseek(FICHIER_DICO, -k, SEEK_CUR);
     
    		}		
    		if (strcmp(mot_lu, mot) == 0)
    		{
    /*			printf("%s = %s, recherche terminee en %d etapes!\n", mot_lu, mot, etape);*/
    			stop = 1;
    		}
    	}	
     
    	fseek(FICHIER_DICO, -leng, SEEK_CUR);
    	fgets(aux, TAILLE_LIGNE_MAX, FICHIER_DICO);
    	strcpy(LIGNE_RENVOYEE, aux);
    /*	
    	printf("taille du fichier: %d octets\n", taille_dico);
    */	
    	fseek(FICHIER_DICO, 0, SEEK_SET);
    	return LIGNE_RENVOYEE;
    }
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    void chercheAmbiguite(char mot[], char exception1[], char exception2[])
    {
    	int i = 0;
    	int length = strlen(mot);
    	char* part1;
    	char* part2;
     
    	for (i = 0; i < length; i++)
    	{
    		part1 = extractPart(mot, 0, i);
    		part2 = extractPart(mot, i+1, length-1);
     
    		if ((strcmp(part1, exception1) != 0) && (strcmp(part1, exception2) != 0) && (strcmp(part2, exception1) != 0) && (strcmp(part2, exception2) != 0))
    		{
    /*
    			printf("%s %s\n", part1, part2);
    */
    			if ((rechercheDichotomique(part1) != "*error") && (strlen(part1) > 1))
    			{
    				if ((rechercheDichotomique(part2) != "*error") && (strlen(part2) > 1))
    				{
    					printf("%s %s   <<< concaténation initiale\n%s %s   <<< partitionnement alternatif; URL équivoque valable!\n", exception1, exception2, part1, part2);
    				}
    			}
    		}
    	}
    }
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    int main(int argc, char ** argv)
    {	
     
    	if (argc != 2)
    	{
    		printf("Un seul mot en argument à la fois, merci.\n");
    		return 0;
    	}
     
    	int i = 0;
    	int nombre_lignes;
    	char* result;
    	char* result2;
    	char ligne_lue[TAILLE_LIGNE_MAX];
    	char* mot_recup = (char*)malloc(TAILLE_LIGNE_MAX * sizeof(char));
     
    /*Affectation des variables relatives à rechercheDichotomique() */	
    	FICHIER_DICO = fopen(DICO, "r");
    	LIGNE_RENVOYEE = (char*)malloc(TAILLE_LIGNE_MAX * sizeof(char));
     
     
    	result = rechercheDichotomique(argv[1]);
     
    	if (strcmp(result, "*error") != 0)
    	{
    		result2 = partOfSpeech(result);
    		printf("%s", result);
    		printf("Classe grammaticale = %s\n", result2);
    	}
    	else
    	{
    		printf("Le mot propose ne fait pas partie du dictionnaire :'-)\n");
    	}
     
    	nombre_lignes = nombreLignes(DICO);	
     
    	FILE* fichier = NULL;
    	fichier = fopen(DICO, "r");
     
    	for (i = 0; i < nombre_lignes; i++)
    	{
    		fgets(ligne_lue, TAILLE_LIGNE_MAX, fichier);
    		getMot(ligne_lue, mot_recup);
    		if (i%1000 == 0)
    		{
    			printf("%dème mot lu = %s\n", i, mot_recup);
    		}
    		chercheAmbiguite(concateneMots(argv[1], mot_recup), argv[1], mot_recup);
    		chercheAmbiguite(concateneMots(mot_recup, argv[1]), mot_recup, argv[1]);
    	}
    	printf("Recherche terminée! :'-)\n");
    	fclose(FICHIER_DICO);
    	fclose(fichier);
    	return 0;
    }
    Le fichier dictionnaire utilisé peut se télécharger ici: http://www.labri.fr/perso/clement/le...ff-2.1.txt.bz2 , et il faut supprimer les lignes du début contenant les CGU ainsi que quelques lignes inutiles à la fin du fichier pour que la recherche dichotomique fonctionne comme il faut.

    Pour les variables globales, je sais que c'est Mal dans l'absolu, mais c'est un de mes profs qui m'a dit que dans ce cas, je peux le faire - et effectivement, ça a résolu mon problème de segfault. Pour le reste de tes "reproches" à mon code, j'espère que le voir en entier répond à ces questions:
    1° Je renvoie la valeur d'une var globale car je la modifie à chaque itération;
    2° Pour la libération, je croyais qu'elle se faisait automatiquement lorsque le programme terminait - si ce n'est pas le cas, je devrai rajouter un free();
    3° Dans le code effectif, ce n'est pas le cas a priori;
    4° Idem, je me suis un peu planté en schématisant la chose au lieu de poster le vrai code =)


    Quant aux mauvaises habitudes, eh bien, en fait ça ne vient pas de Java. Je suis en licence d'info, mais j'y suis entré par équivalence, et je n'ai jamais vraiment fait d'info avant, donc j'ai appris à faire du C au premier semestre... donc mea culpa pour mes maladresses =)




    En tout cas... Je viens de refaire le test, et cette fois-ci j'ai également un segfault, mais plus après test de 15k mots du dico, mais 195k. Donc sortir le fopen et le malloc de la fonction rechercheDichotomique a l'air d'avoir aidé, mais pas résolu le problème...

  5. #5
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    En jetant un coup d'œil rapide à ton programme, il y a au moins trois problèmes assez important :

    • Un non respect du const-correctness.
    • Énormément d'allocation mais aucune libération.
    • Aucun test sur les valeurs de retours des fonctions malloc() et fopen().


    Le second point peut conduire, comme l'a précédemment fait remarquer Obsidian, à un manque de ressource.
    Le troisième peut conduire à un crash lorsque malloc() retourne NULL pour indiquer un échec d'allocation[1].



    [1] Petite digression au passage, suivant la manière dont est utilisé la mémoire alloué, le test du retour de malloc() ne prévient pas toujours à lui seul les problème lorsque l'allocateur mémoire utilise la stratégie appelé "Optimistic memory allocation"

  6. #6
    Membre éclairé Avatar de mikhailo
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    78
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 78
    Par défaut
    Pour les tests de retour de malloc() et fopen() je suis d'accord, je vais le rajouter.

    En revanche, qu'entends-tu par non respect de const-correctness?

    Et pour ce qui est des allocations et pas de libérations:
    • Le fopen() et les malloc() du main ne sont appelés qu'une fois car à l'extérieur de toute boucle, donc certes il est plus propre de free() ça à la fin du programme, mais ce n'est pas censé faire planter l'exécution de la boucle
    • Je peux "sortir" de la même façon le malloc() de la fonction concateneMots et le free() à la fin de l'exécution; pas de soucis car à chaque fois je fais un strcpy() dans la variable;
    • Ce qui fait que dans la boucle il ne reste que le malloc() de la fonction extractPart. J'ai déjà testé, si je le "sors" de la même façon, ça donne n'importe quoi au niveau de l'output; il faut vraiment que ce soit reinitialisé à chaque fois. Et je ne peux pas le free(), car je return la variable en question!


    Que devrais-je faire pour remédier à ça?

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo