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

MFC Discussion :

Fonctionne en Debug mais pas en Release


Sujet :

MFC

  1. #1
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut Fonctionne en Debug mais pas en Release
    Voilà je développe un petit programme solveur de sudoku (je m'ennui ^^)

    Et je suis tombé sur un petit problème. Mon application fonctionne si elle a été compilée en Debug, mais ne fonctionne pas correctement si elle a été compilée en Release.

    Evidemment, je n'ai pas touché aux paramètres de compilation.

    Mon erreur est par là :
    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
     
    // rappel:
    char map[82];
    CEdit* edit[81];
    // code:
    	char t;
    	CEdit *e;
    	CString str;
    	for(int a=0; a<81; a++) {
    		e = edit[a];
    		e->GetWindowTextW(str);
    		if(str.GetLength()) {
    			t = str.GetAt(0) - '0';
    			ASSERT(t>0);
    			ASSERT(t<=9);
    		}
    		else t = 0;
    		map[a] = t;
    	}
    Seulement voilà, en mode Debug, celà fonctionne : si le CEdit est vide, alors il ajoute 0 dans mon tableau...
    En mode Release, (Visual catch moins d'info?!) je peux voir que mon tableau map ne change pas malgré les affectations...

    ça m'embête un peu car la version Debug fait 2,7 Mo, la Release en fait 330 k...

    Quelqu'un a une idée?

  2. #2
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    J'ai triffouillé les options,
    en changeant ceci dans les options de configuration Release/Win32:

    Optimisation de "/O2" -> "/Od" (dans C/C++ > Optimisation)
    Vérification d'exécution de "Par défaut" à "Les deux" (dans C/C++ > Génération de code)

    Maintenant ça fonctionne, mais je n'ai toujours pas compris pourquoi...

  3. #3
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    salut,
    je pense que tu as simplement déplacé le probléme en mémoire ...
    ce genre de bug est souvent le signe d'un débordement mémoire.
    note que si tu travailles en unicode tu devrais utiliser TCHAR au lieu de char..

  4. #4
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    Je pense aussi (que j'ai simplement déplacé le problème), mais si je n'en ai aucune preuve;

    En fait, mon tableau de caratères (char map[82])
    contient 81 valeurs (du ASCII 0 à ASCII 9). 81 valeurs = 9x9 (grille sudoku) (un zéro signifiant : pas de chiffre dans la case)
    Et le 82ème char c'est pour mettre un zéro, et "caster" ma grille en char*

    Pour vérifier si ma grille est complète, je fais strlen(map)==81;

    Bref,
    je remplis mon tableau des valeurs comprises entre 1 et 9, selon la valeur des CEdit. Si le CEdit est vide alors je met un zéro.

    en mode release je mets un point d'arrêt avant le for et je vois qu'il entre bien dedans, et qu'il passe dans l'affectation, (dans VS, je mets ma souris sur la variable "map") et je vois que les affectations ne sont pas prises en comptes, et que map contient encore les valeurs en mémoire au moment de la déclaration.

    J'ai rajouté un memset(map,0,82), ce qui, avant d'entrer dans le for, remplis mon tableau de zéro. En débug, celà fonctionne. En release, le memset n'a pas changé les valeurs de map.

    Je soupçonne VS de me donner des indications erronées (en mode release, il a moins d'informations de débug) ...

  5. #5
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 386
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 386
    Points : 20 468
    Points
    20 468
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    char map[82];
    CEdit* edit[81];
    // code:
    	char t;
    	CEdit *e;
    	CString str;
    	for(int a=0; a<81; a++) {
    		e = edit[a];

    Le code est perfectible :
    D"abord un controle se crée en générale avec CWnd::Create ensuite utilise un CArray ou CList plutot qu'un tableau statique

    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
     
    CArray <CEdit*,CEdit*> ArrayEditCtrl;
    //.......
     
    CRect rect;
    int nEditBoxTop=10;
    int nEditBoxID=100; // voir avec fichier RC
    rect.top =nEditBoxTop;
    rect.bottom =rect.top +20;
    rect.left =10;
    rect.right=rect.left+100;
    CEdit *pEdit= new CEdit;  // NE Pas oublier delete
    pEdit->CreateEx (WS_EX_CLIENTEDGE, _T ("EDIT"), NULL,
    WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP , rect, this, nEditBoxID);
    ArrayEditCtrl.Add (pEdit);
    pEdit->EnableWindow (TRUE);
    pEdit->SetWindowText ("Edit");
    nEditBoxID++;
    nEditBoxTop+=30
    Boucler de 0 à 80 pour créer une matrice.
    Au besoin sublcasser pEdit pour recevoir les messages

  6. #6
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    Le code que j'ai donné est placé dans l'évènement d'un clic sur un bouton.

    A mon OnInitDialog, j'ai ceci:
    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
     
    	int a;
    	CEdit *e;
    	for(int j=0; j<9; j++) {
    		for(int i=0; i<9; i++) {
    			a = j*9+i;
    			e = new CEdit();
    			RECT r;
    			r.left = 10+i*28;
    			r.top = 10+j*28;
    			r.right = 10+i*28+22;
    			r.bottom = 10+j*28+22;
    			e->Create(ES_CENTER|WS_VISIBLE|ES_NUMBER|WS_TABSTOP,r,this,a+1000);
    			e->SetWindowTextW(CString());
    			edit[a] = e;
    		}
    	}
    Je créé donc des CEdit, qui s'affichent et fonctionnent correctement. Et je les référence dans un tableau CEdit* edit[81];

    Je n'ai pas besoin de recevoir les messages de mes CEdit (sauf peut être faire un DDV pour limiter a un seul chiffre par cases)

    Et je ne vois pas l'intéret d'utiliser un CArray ou une CList, si je n'ai pas l'intention d'ajouter (insérer) un élément pendant l'exécution.

    PS: mon application est assez bas niveau je le reconnais, mais ça ne devrait pas posser de soucis majeurs ?

  7. #7
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 386
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 386
    Points : 20 468
    Points
    20 468
    Par défaut
    Citation Envoyé par Baud10 Voir le message
    Je créé donc des CEdit, qui s'affichent et fonctionnent correctement. Et je les référence dans un tableau CEdit* edit[81];


    Et je ne vois pas l'intéret d'utiliser un CArray ou une CList, si je n'ai pas l'intention d'ajouter (insérer) un élément pendant l'exécution.
    1-ton code n'est pas très propre et un peu fouilli
    2 pourquoi utiliser un CArray ? Parce que c'est plus propre , que c'est conteneur ,que cela s'intégre mieux avec le reste du Framwork et que cela permet de gérer les exceptions surtout ce que ne permet pas char []..
    Et en plus CArray te donne les fuites de mémoires contrairement à char[].

  8. #8
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    Je sais que mon implémentation m'oblige a parcourir mon tableau pour deleter chaque élément, dans le destructeur de ma boîte de dialogue. Mais je n'ai aucune fuite mémoire.

    Moi je n'aime pas trop les CArray (j'ai été habitué aux std::list, std::map et leurs itérateurs).

    Dans ton code exemple, tu mets ceci:
    CArray <CEdit*,CEdit*> ArrayEditCtrl;

    Je ne comprend pas très bien pourquoi le template contient 2 pointeurs de CEdit ?
    On pourrait très bien faire :
    CArray<CEdit*> ?
    J'ai déjà utilisé le CArray : ici encore, je devrais deleter mes éléments "a la main". Et je n'ai pas le parcour d'un CArray (for(int i=0; i<array.GetCount(); i++)... (là encore aucune différence avec mon tableau de CEdit*).

    Même mieux (même si je ne l'ai jamais utilisé, je pense que ça sert à ça) :
    CTypedPtrArray<CEdit*> ? (le delete de ce template détruira tous les objets qu'il référence?)

    Je vais adapter mon code en utilisant un conteneur plus propre (je voulais à la base quelque chose d'hyper-performant et j'ai donc utilisé un tableau de CEdit et de char). Et on verra

  9. #9
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    tu n'as pas répondu a ma question sur le fait que ton projet soit unicode ou non ...

  10. #10
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    Je ne sais pas top où trouver ça (j'ai pas touché a la case à cocher, lors de la création du projet). Dans les options de build, j'ai trouvé ça :

    /Od /GL /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /FD /EHsc /RTC1 /MT /Yu"stdafx.h" /Fp"Release\Sodoku.pch" /Fo"Release\\" /Fd"Release\vc80.pdb" /W3 /nologo /c /Wp64 /Zi /TP /errorReport:prompt


    Donc le projet doit être UNICODE...

  11. #11
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    donc ma suggestion précédente devient pertinente ...
    soit tu passes en MBCS et tu peux travailler avec des char.
    sur le projet : propriétés/générales/jeu de caractères: Utiliser le jeu de caractères multioctet (MBCS)
    soit tu restes en UNICODE et tu utilises TCHAR à la place de char .
    la macro _T("") pour les chaines etc..
    note que TCHAR permet de travailler dans les deux modes.

  12. #12
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 386
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 386
    Points : 20 468
    Points
    20 468
    Par défaut
    Citation Envoyé par Baud10 Voir le message
    Moi je n'aime pas trop les CArray (j'ai été habitué aux std::list, std::map et leurs itérateurs).
    [apparte]
    LA STL est très bien aussi mais parfois je préfère utiliser par exemple CString , quand c'est possible ( projet MFC ) plutot que std:string pas forcément toujours simple et intuitive
    Dans un projet MFC je prends des classes MFC, dans un projet non MFC je prend la STL
    [/apparte]

  13. #13
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    J'ai continué a chercher d'où provenait l'erreur.

    Premièrement, le mode débogueur de visual n'a pas l'air notifié des changements de valeurs des variables (en mode Release) donc je ne peux pas me baser sur lui pour trouver l'erreur :
    for(int i=0; i<81; i++)
    if(map[i]) return;

    (si une valeur de map est non-nulle, le programme ne poursuit pas. a l'exécution il se poursuit : conclusion, les 81 premières valeurs de map sont nules, ce qui est l'état normal. si je met ma souris sur la variable map, les valeurs qu'ils m'indique ne sont pas du tout bonnes, ne sont pas des zéro. Et ce, que je sois avec un tableau de char[82] ou de int[81] car je n'ai pas besoin de la sémantique de chaine de caractère mais plutot de tableau de chiffre).

    En poursuivant mes investigations, c'est en appelant une de mes fonction que ça coince :

    compilé en debug, la fonction n'écrit rien.
    compilé en mode release, la fonction écrit plusieurs fois dans map. (a chaque fois je lance l'application sans remplir une seule valeur dans mes CEdit).

    Ma fonction doit rechercher ce qu'on appel les "naked pair", c'est à dire deux cases vide sur une même ligne / colonne / bloc de sudoku, qui ne peuvent avoir que deux possibilités, et ces deux possibilités sont les mêmes pour ces deux cases. Alors toutes les autres cases de la ligne/colonne/bloc ne peuvent plus avoir ces deux possibilités.

    Le code est assez complexe, mais le-voici quand même:

    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
    int CSudokuDlg::resol_double()
    {
    	int n = 0, t;
    	// création de l'arbre:
    	for(int a=0; a<81; a++) {
    		if(!map[a])
    			memset(table, 0, 81);
    	}
    	bool *pass2;
    	// générer la table
    	for(int j=0; j<9; j++) {
    		for(int i=0; i<9; i++) {
    			// travail pour la case i,j
    			if(map[i+9*j])
    				continue; // ce n'est pas un trou
    			pass2 = table[i+9*j];
    			for(int a=0; a<9; a++) { // élimination des candidats mode LIGNE
    				if(t = map[a+9*j])
    					pass2[t] = 1;
    				if(t = map[i+9*a]) // ... et COLONNE
    					pass2[t] = 1;
    			}
    			for(int a=0; a<3; a++) { // mode CUBE
    				for(int b=0; b<3; b++) {
    					if(t = map[3*(i/3)+a+9*(3*(j/3)+b)])
    						pass2[t] = 1;
    				}
    			}
    		}
    	}
    retry:
    	// chercher pour chaque trou de chaque ligne/colonne/bloc
    	// s'il y a pas 2 cases qui ont que 2 possibilités et qu'elles soient identiques
    	// éliminer les possibilités
    	int f,a1,a2,b1,b2;
    	for(int j=0; j<9; j++) {
    		for(int i=0; i<9; i++) {
    			if(map[i+9*j])
    				continue; // ce n'est pas un trou
    			pass2 = table[i+9*j];
    			f = 0;
    			for(int k=1; k<10; k++) {
    				if(pass2[k]) {
    					f++;
    					if(f) // systémtatiquement dans le même ordre (de a=1 à a=10)
    						a2 = k;
    					else
    						a1 = k;
    				}
    			}
    			if(f==2) { // on a trouvé une case a 2 candidats
    				// rechercher pour cette case, tous les trous suivants
    				// de cette ligne, qui ont eux-aussi que 2 candidats et les mêmes
    				for(int a=i+1; a<9; a++) { // recherche en LIGNE
    					if(map[a+9*j])
    						continue; // ce n'est pas un trou
    					f = 0;
    					for(int k=1; k<10; k++) { // recherche du nombre de possibilité pour la case courrante
    						if(pass2[k]) {
    							f++;
    							if(f)
    								b2 = k;
    							else
    								b1 = k;
    						}
    					}
    					if(f==2) {
    						if(a1 == b1 && a2 == b2) { // la case courrante est une paire cachée avec I,J
    							// I,J vaut A1 OU B1
    							// A,J vaut l'autre
    							// éliminer de la table A1 et B1 du reste de la ligne!
    							for(int b=0; b<9; b++) {
    								if(b == i || b == a) // X des paires
    									continue;
    								table[b+9*j][a1] = 1; // ne peut plus être
    								table[b+9*j][b1] = 1;
    							}
    						}
    					}
    				} // mode ligne
    				for(int a=i+1; a<9; a++) { // recherche en COLONNE
    					if(map[i+9*a])
    						continue; // ce n'est pas un trou
    					f = 0;
    					for(int k=1; k<10; k++) {
    						if(pass2[k]) {
    							f++;
    							if(f)
    								b2 = k;
    							else
    								b1 = k;
    						}
    					}
    					if(f==2) {
    						if(a1 == b1 && a2 == b2) { // la case courrante est une paire cachée avec I,J
    							for(int b=0; b<9; b++) {
    								if(b == j || b == a) // Y des paires
    									continue;
    								table[i+9*b][a1] = 1; // ne peut plus être
    								table[i+9*b][b1] = 1;
    							}
    						}
    					}
    				} // mode colonne
    				for(int a=0; a<3; a++) { // recherche en CUBE
    					for(int b=0; b<3; b++) {
    						if(a==i%3 && b==j%3)
    							continue; // case courrante
    						if(map[3*(i/3)+a+9*(3*(j/3)+b)])
    							continue; // ce n'est pas un trou
    						f = 0;
    						for(int k=1; k<10; k++) {
    							if(pass2[k]) {
    								f++;
    								if(f)
    									b2 = k;
    								else
    									b1 = k;
    							}
    						}
    						if(f==2) {
    							if(a1 == b1 && a2 == b2) { // la case courrante est une paire cachée avec I,J
    								for(int c=0; c<3; c++) {
    									for(int d=0; d<3; d++) {
    										if(c+(i/3)*3 == i && d+(j/3)*3 == j) // première paire (original)
    											continue;
    										if(c == a && d == b) // seconde paire (trouvé)
    											continue;
    										table[3*(i/3)+c+9*(3*(j/3)+d)][a1] = 1; // ne peut plus être
    										table[3*(i/3)+c+9*(3*(j/3)+d)][b1] = 1;
    									}
    								}
    							}
    						}
    					}
    				} // mode cube
    			} // if(f==2)
    		}
    	} // comparaison
    	int e, n2 = 0;
    	for(int i=0; i<9; i++) { // reconstitution...
    		for(int j=0; j<9; j++) {
    			if(map[i+9*j])
    				continue;
    			f = 0;
    			for(int a=1; a<10; a++) {
    				if(table[i+9*j][a])
    					f++;
    				else
    					e = a;
    			}
    			if(f==8) { // on a éliminé 8 possibilités. En resite qu'une
    				map[i+9*j] = e;
    				n++;
    				n2++;
    			}
    		}
    	}
    	if(n2)
    		goto retry;
    	resultat[5] += n;
    	return n;
    }
    Je vais retirer le GOTO, et mettre un while (parrait que GOTO c'est pas propre)

    PS:
    resultat est membre de la classe (int resultat[10])
    table est membre de la classe (bool [81][10])

  14. #14
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    @Mat : moi je n'aime pas trop les CString (notamment car c'est difficile a en extraire le char*), mais je n'utiliserai pas la STL dans un projet MFC.

    @tout le monde:
    j'aimerai savoir comment se comporte memset ?
    si je lui passe un tableau de int, il va mettre que 8 des 32 bits de chaque int à zéro ? comment initialiser un tableau de int à zéro, un for ?

  15. #15
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    Voilà j'ai trouvé...

    dans le code que j'ai montré, j'ai mis ceci:
    memset(table, 0, 81);
    mais ça aurait du être ceci:
    memset(table[a], 0, 10);

    [edit]

    conclusion :
    en debug, memset(table, 0, 81); fonctionne, pas en release

  16. #16
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    il faut utiliser sizeof pour ce genre de chose...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    memset(table, 0, sizeof(table));
    note:il est très simple d'extraire un char,une chaine d'une CString , tu as l'opérateur [] ou GetAt() ,LPCTSTR pour la chaine.

  17. #17
    Membre du Club Avatar de Baud10
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2006
    Messages : 66
    Points : 47
    Points
    47
    Par défaut
    Je me suis mal exprimé. Il est très difficile d'obtenir le "char*" d'une CString. Soit on parcour à la main de 0 à GetLength(), et on ajoute le caractère GetAt() dans notre char*, soit on utilise MultiByteToWideChar...

    soit on cast en LPCTSTR ? j'essairai. J'ai cru entendre que ça ne marchait plus sous visual 8.


    Je ne connais pas très bien le fonctionnement de memset : prend un pointeur d'une variable quelquonque, on lui donne avec quelle valeur a initialiser, et le nombre d'élément/d'octets a initialiser.

    Si on lui passe un tableau de 10 entiers, et on lui demande d'initialiser tout le tableau à 1 des 10 entiers : memset(tableau, 1, 10). Que va-t-il se passer ?

    Deux possibilités :
    1) Est-ce que les 10 entiers vaudront la valeur 1 ?
    2) Est-ce que les 10 (premiers) octets du tableau sera mis à un : un int est codé sur 4 octets (sur une architecture 32 bits). Soit chaque octet au lieu de valoir : 0x00000001 vaudra 0x01010101 (ce qui vaut 16843009) ?

    Si c'est la solution N°2, comment initialiser un tableau d'un type de variable stoqué sur plus d'un octets sans utiliser un for ?

    Est-ce qu'un bool est codé sur un octet ? Un bool est en fait en mémoire comme un unsigned char ?


    Seconde chose. sizeof() retourne quoi exactement. La longueur (en octets) d'une variable ? ou le nombre d'éléments qu'elle contient?
    Si c'est la longueur, pour obtenir le nombre d'élément faut faire alors sizeof(mavar)/sizeof(int) ?

    Désolé mais ces opérations bas niveau je les utilises trop souvent a mauvais escient et j'aimerais comprendre

    En tout cas merci farscape et aux autres, pour cette aide

  18. #18
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    memset ignore le type d'élément passé, l'argument attendu est un pointeur void sur une zone mémoire.
    la longueur a donner est donc le nombre d'octets de cette zone.
    sizeof retourne en octet la taille de l'élément passé en argument.
    si mavar est un tableau de int alors oui sizeof(mavar)/sizeof(int) retourne le nombre d'éléments de mavar.

  19. #19
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Citation Envoyé par Baud10 Voir le message
    Je me suis mal exprimé. Il est très difficile d'obtenir le "char*" d'une CString. Soit on parcour à la main de 0 à GetLength(), et on ajoute le caractère GetAt() dans notre char*, soit on utilise MultiByteToWideChar...

    soit on cast en LPCTSTR ? j'essairai. J'ai cru entendre que ça ne marchait plus sous visual 8.
    Là, il est question de deux choses différentes:
    • Récupérer un pointeur vers les caractères d'une CString
    • Récupérer un char* ou const char * d'une CString pouvant être unicode.

    Sous une version >6 de MFC, la classe CString est (enfin!) décomposée en deux classes CStringA et CStringW, chacune pouvant être construite à partir de l'autre. Donc, quand tu as besoin d'un const char *, tu peux créer une CStringA à partir de ta CString, indépendamment du fait de compiler ou non en unicode...
    (sachant que si tu ne compiles pas en unicode, il n'y aura pas de copie inutile, puisque les CStrings utilisent un comptage de références et le Copy-On-Write...)

    Quant à l'obtension du nombre d'élements d'un tableau, je conseille d'utiliser la macro VC ARRAYSIZE() qui, en C++, donne une erreur de compilation si on lui passe un pointeur au lieu d'un tableau.

  20. #20
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 4
    Points : 5
    Points
    5
    Par défaut
    Pour ma part j'utilise une classe de base de la stl qui s'appelle string.
    ou pour faire des tableaux et des listes vector ou list

    C'est quand même plus simple et plus propre.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 5
    Dernier message: 03/02/2015, 15h18
  2. Réponses: 5
    Dernier message: 20/09/2014, 07h36
  3. programme fonctionne en debug mais pas en release ?
    Par membreComplexe12 dans le forum C++
    Réponses: 20
    Dernier message: 16/05/2012, 11h52
  4. Réponses: 6
    Dernier message: 14/06/2011, 18h39
  5. regsvr32 failed en debug mais pas en release
    Par afan dans le forum DirectX
    Réponses: 1
    Dernier message: 09/06/2004, 10h32

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