[C] System.AccessViolationException
Résolu
Utilisateur anonyme
-
Utilisateur anonyme -
Utilisateur anonyme -
8 réponses
1 - Comment se fait-il qu'un tableau commence à 0 ??
Ben, ça toujours été comme ça. Et c'est logique :
toto[0] signifie toto+0, on ne perd pas de case mémoire.
printf(db_registry[0][0]);
Ecriture très dangereuse. Mets plutôt : printf("%s",db_registry[0][0]);
char * full_key = strcat(db_registry[i][0], db_registry[i][1]);
Aïe.
db_registry[i][j] est de type char* (c'est-à-dire pointeur sur une zone en lecture seule). Autrement dis, tu cherches à écriture dans une lecture en lecture seule. Et là, ça passe pas.
Utilise plutôt un malloc au lieu du char*. Et alloue une zone suffisamment grande.
Ben, ça toujours été comme ça. Et c'est logique :
toto[0] signifie toto+0, on ne perd pas de case mémoire.
printf(db_registry[0][0]);
Ecriture très dangereuse. Mets plutôt : printf("%s",db_registry[0][0]);
char * full_key = strcat(db_registry[i][0], db_registry[i][1]);
Aïe.
db_registry[i][j] est de type char* (c'est-à-dire pointeur sur une zone en lecture seule). Autrement dis, tu cherches à écriture dans une lecture en lecture seule. Et là, ça passe pas.
Utilise plutôt un malloc au lieu du char*. Et alloue une zone suffisamment grande.
Coucou Fiddy,
Pourquoi ?
toto[0] ne vaut pas le nombre de lignes ?
Peux-tu m'expliquer cela ?
char * = C'est un pointeur (zone en mémoire) vers une chaîne de caractères, elle n'est pas modifiable ?
Et je le place comment mon malloc ?
Qu'est-ce que je dois mettre en mémoire ?
Pas de sizeof() pour le malloc ?
Merci de ta réponse :-)
printf(db_registry[0][0]); Ecriture très dangereuse. Mets plutôt : printf("%s",db_registry[0][0]);
Pourquoi ?
Ben, ça toujours été comme ça. Et c'est logique : toto[0] signifie toto+0, on ne perd pas de case mémoire.
toto[0] ne vaut pas le nombre de lignes ?
db_registry[i][j] est de type char* (c'est-à-dire pointeur sur une zone en lecture seule)
Peux-tu m'expliquer cela ?
char * = C'est un pointeur (zone en mémoire) vers une chaîne de caractères, elle n'est pas modifiable ?
Et je le place comment mon malloc ?
Qu'est-ce que je dois mettre en mémoire ?
Pas de sizeof() pour le malloc ?
Merci de ta réponse :-)
printf(db_registry[0][0]);
Ecriture très dangereuse. Mets plutôt : printf("%s",db_registry[0][0]);
Car printf est de type printf(const char*format, ...). Avec ce genre de code, un pirate pourrait s'amuser à lire des zones en mémoire. Par exemple si db_registry[0][0] contient des %s ou autre.
toto[0] ne vaut pas le nombre de lignes ?
Non. int toto[3]={1,2,3}; En mémoire, l'adresse mémoire est toto qui contient la valeur 1, à l'adresse toto+1, on a 2, et à toto+2 on a 3.
char * = C'est un pointeur (zone en mémoire) vers une chaîne de caractères, elle n'est pas modifiable ?
Cela dépend de ce que tu mets derrière.
char *chaine="toucou"; A l'adresse mémoire toto, tu as l'adresse de la chaîne "toucou" (stocké dans la zone en lecture seule). Tu ne pourras donc pas faire chaine[0]='c';
En revanche, tu pourras bien faire chaine="coucou"; (mais ce sera une autre chaîne).
Et je le place comment mon malloc ?
Par exemple, char * db_registry [size_reg_key][2]=malloc(255); ou alors db_registry [size_reg_key][2][255] =
Pas de sizeof() pour le malloc ?
Si tu fais char*toto=malloc(10);
sizeof(toto)=4 (cela dépend de la machine) car toto est un pointeur (char *)
Mais, si tu fais char toto[10], sizeof(toto) = 10; car toto est un tableau.
Ecriture très dangereuse. Mets plutôt : printf("%s",db_registry[0][0]);
Car printf est de type printf(const char*format, ...). Avec ce genre de code, un pirate pourrait s'amuser à lire des zones en mémoire. Par exemple si db_registry[0][0] contient des %s ou autre.
toto[0] ne vaut pas le nombre de lignes ?
Non. int toto[3]={1,2,3}; En mémoire, l'adresse mémoire est toto qui contient la valeur 1, à l'adresse toto+1, on a 2, et à toto+2 on a 3.
char * = C'est un pointeur (zone en mémoire) vers une chaîne de caractères, elle n'est pas modifiable ?
Cela dépend de ce que tu mets derrière.
char *chaine="toucou"; A l'adresse mémoire toto, tu as l'adresse de la chaîne "toucou" (stocké dans la zone en lecture seule). Tu ne pourras donc pas faire chaine[0]='c';
En revanche, tu pourras bien faire chaine="coucou"; (mais ce sera une autre chaîne).
Et je le place comment mon malloc ?
Par exemple, char * db_registry [size_reg_key][2]=malloc(255); ou alors db_registry [size_reg_key][2][255] =
Pas de sizeof() pour le malloc ?
Si tu fais char*toto=malloc(10);
sizeof(toto)=4 (cela dépend de la machine) car toto est un pointeur (char *)
Mais, si tu fais char toto[10], sizeof(toto) = 10; car toto est un tableau.
Avec ce genre de code, un pirate pourrait s'amuser à lire des zones en mémoire. Par exemple si db_registry[0][0] contient des %s ou autre.
Puis-je avoir un peu plus d'explication là dessus ? Il lira le contenu de mon: db_registry ?
</code> malloc(sizeof(db_registry));</code>
ça ça ne marche pas ? J'aimerais un truc du genre pour ne pas avoir à déclarer un buffer trop grand ou trop petit, ce n'est pas "propre". :-)
Et je le place comment mon malloc ?
Par exemple, char * db_registry [size_reg_key][2]=malloc(255); ou alors db_registry [size_reg_key][2][255] =
Désolé rien compris,
Merci de ton aide,
sizeof(db_registry) ne te renvoi pas la longueur de la chaine.
La première chose à faire lorsque l'on utilise une fonction est de regardé son manuel http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/strcat.3.html
en gros,
ne pas oublier aussi qu'à chaque malloc doit correspondre un free, sinon gare aux fuites de mémoire (ton programme prend de la taille jusqu'à l'infini).
Pour revenir sur l'histoire du toto[0]; Un pointeur est une adresse mémoire, pour lire ce qu'il y a en mémoire, on utiliser l'opérateur '*' (*toto est la valeur de la case mémoire toto). Lorsqu'on alloue de la mémoire de manière "étendu" avec malloc, on peut alors accéder à cette mémoire par block (dépendant du type sous jacent du pointeur). toto[2] est le 3ème bloc mémoire. Il y a une autre façon d'accéder à cette mémoire, toto étant toujours une adresse mémoire (le début de la zone) si on se déplace un peu on accède aux autres données : *(toto+2) est la troisième case. *(toto+0) est la première. D'où le commencement à 0.
La première chose à faire lorsque l'on utilise une fonction est de regardé son manuel http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/strcat.3.html
en gros,
char *fullkey=malloc(strlen(db_registry[i][0]+strlen(db_registry[i][1]) ); strcat(fullkey,db_registry[i][0]); strcat(fullkey,db_registry[i][1]);
ne pas oublier aussi qu'à chaque malloc doit correspondre un free, sinon gare aux fuites de mémoire (ton programme prend de la taille jusqu'à l'infini).
Pour revenir sur l'histoire du toto[0]; Un pointeur est une adresse mémoire, pour lire ce qu'il y a en mémoire, on utiliser l'opérateur '*' (*toto est la valeur de la case mémoire toto). Lorsqu'on alloue de la mémoire de manière "étendu" avec malloc, on peut alors accéder à cette mémoire par block (dépendant du type sous jacent du pointeur). toto[2] est le 3ème bloc mémoire. Il y a une autre façon d'accéder à cette mémoire, toto étant toujours une adresse mémoire (le début de la zone) si on se déplace un peu on accède aux autres données : *(toto+2) est la troisième case. *(toto+0) est la première. D'où le commencement à 0.
Huuummmm, d'accord !
J'ai compris, le pointeur et la mémoire :-)
Cependant, est-ce là même chose ici avec DWORD ?
J'ai compris, le pointeur et la mémoire :-)
Cependant, est-ce là même chose ici avec DWORD ?
#define size_files 2 char * db_files [size_files] = {"C:\\force_delete.txt", "C:\\ComboFix.txt"}; DWORD Attributes; for (i = 0 ; i < size_files ; i++) { if (_access(db_files[i], 0) != -1) { hFile = CreateFileA((LPCSTR) db_files[i], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) { // Convert the created time to local time. set +1 FileTimeToSystemTime(&ftCreate, &stUTC); SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); Attributes = GetFileAttributesA(db_files[i]); fprintf(rapport, "0x%x - [%02d/%02d/%d %02d:%02d] - %s\n", Attributes, stLocal.wDay, stLocal.wMonth, stLocal.wYear, stLocal.wHour, stLocal.wMinute, db_files[i]); } else { fprintf(rapport, "[error: %d] : %s\n", GetLastError(), db_files[i]); } CloseHandle(hFile); } }
Oui, là même, mais avec un autre bout de code.
Cela se produit lorsque je mets:
Dans le fprintf.
Et je ne sais pas d'où cela peut provenir, souhaites-tu une capture ?
Cela se produit lorsque je mets:
fprintf(rapport, "0x%x - [%02d/%02d/%d %02d:%02d] - %s\n", Attributes, stLocal.wDay, stLocal.wMonth, stLocal.wYear, stLocal.wHour, stLocal.wMinute, db_files[i]);
Dans le fprintf.
Et je ne sais pas d'où cela peut provenir, souhaites-tu une capture ?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Bonjour,
J'ai préféré te donner tout le code, il n'y a pas grand chose:
https://pjjoint.malekal.com/files.php?read=20121006_z14u8k12n14g9
Sachant aussi que j'ai un autre sujet en cours:
https://forums.commentcamarche.net/forum/affich-26195289-c-handle
Pour pouvoir créer un handle sur un dossier :-)
Deux sujets car deux problèmes différents,
Merci ;-)
J'ai préféré te donner tout le code, il n'y a pas grand chose:
https://pjjoint.malekal.com/files.php?read=20121006_z14u8k12n14g9
Sachant aussi que j'ai un autre sujet en cours:
https://forums.commentcamarche.net/forum/affich-26195289-c-handle
Pour pouvoir créer un handle sur un dossier :-)
Deux sujets car deux problèmes différents,
Merci ;-)
fprintf(rapport, "[%02d/%02d/%d %02d:%02d] - %s\n", Attributes, stLocal.wDay, stLocal.wMonth, stLocal.wYear, stLocal.wHour, stLocal.wMinute, db_files[i]);
Tu as 5%d et 1%s pour 7 variables. Il manque quelquechose.
const char * report_path = strcat(getenv("HOMEDRIVE"),"\\SHZ_LookUp.txt");
Bizarre que cela ne plante pas.
Pour info, strcat concatène les deux arguments et mets le résultat dans la première variable (ici getenv("HOMEDRIVE")).
Tu as 5%d et 1%s pour 7 variables. Il manque quelquechose.
const char * report_path = strcat(getenv("HOMEDRIVE"),"\\SHZ_LookUp.txt");
Bizarre que cela ne plante pas.
Pour info, strcat concatène les deux arguments et mets le résultat dans la première variable (ici getenv("HOMEDRIVE")).
Tu as 5%d et 1%s pour 7 variables. Il manque quelquechose.
J'ai enlevé le: " 0x%x", mais oublié d'enlever le: Attributes (à force de test), si je rajoute le: " 0x%x", j'obtiens l'erreur.
Je pensais à balancer trop d'informations dans le printf / fptrintf qui le faisait hurler pour la mémoire.
Pour info, strcat concatène les deux arguments et mets le résultat dans la première variable (ici getenv("HOMEDRIVE")).
Je ne comprends pas ce que tu veux, dire... Mais comme je l'ai fait, cela fonctionne parfaitement, pour cela que j'étais étonné que ça ne fonctionne pas (voir mon post initial).
Je pensais à balancer trop d'informations dans le printf / fptrintf qui le faisait hurler pour la mémoire.
Pas avec si peu d'informations. Il y a certainement une erreur ailleurs.
Je ne comprends pas ce que tu veux, dire... Mais comme je l'ai fait, cela fonctionne parfaitement, pour cela que j'étais étonné que ça ne fonctionne pas (voir mon post initial).
Ce n'est pas parce que ça fonctionne cette fois que c'est correct. Cela provoque des débordements en écriture en mémoire. Cela fonctionne jusqu'au jour où on se demande ce qui se passe. C'est ce genre d'erreur qui peut modifier des variables, et provoquer des bugs plus loin dans le code...
Je rexplique plus en détails :
char dest[100]="Bonjour ";
char src[]="Saachaa";
strcat(dest,src);
//dest a été modifié. Désormais dest vaut : "Bonjour Saachaa";
Là j'ai mis : char dest[100]; donc il y a de la place pour contenir "Saachaa". S'il n'y avait pas la place (genre char dest[9];) cela pourrait s'avérer catastrophique (sans pour autant bugguer immédiatement).
Dans ton strcat(getenv(...)), tu vas faire pareil. Tu vas rajouter "\\SHZ_..." à la suite de la chaîne pointée par getenv(...) dont tu ne peux pas gérer l'allocation.
Il faut donc allouer une chaîne :
char fichier[255]; //ou avec malloc
strcpy(fichier,getenv(...)); //ou encore mieux avec strncpy
strcat(fichier, "\\SHZ_...");
Pas avec si peu d'informations. Il y a certainement une erreur ailleurs.
Je ne comprends pas ce que tu veux, dire... Mais comme je l'ai fait, cela fonctionne parfaitement, pour cela que j'étais étonné que ça ne fonctionne pas (voir mon post initial).
Ce n'est pas parce que ça fonctionne cette fois que c'est correct. Cela provoque des débordements en écriture en mémoire. Cela fonctionne jusqu'au jour où on se demande ce qui se passe. C'est ce genre d'erreur qui peut modifier des variables, et provoquer des bugs plus loin dans le code...
Je rexplique plus en détails :
char dest[100]="Bonjour ";
char src[]="Saachaa";
strcat(dest,src);
//dest a été modifié. Désormais dest vaut : "Bonjour Saachaa";
Là j'ai mis : char dest[100]; donc il y a de la place pour contenir "Saachaa". S'il n'y avait pas la place (genre char dest[9];) cela pourrait s'avérer catastrophique (sans pour autant bugguer immédiatement).
Dans ton strcat(getenv(...)), tu vas faire pareil. Tu vas rajouter "\\SHZ_..." à la suite de la chaîne pointée par getenv(...) dont tu ne peux pas gérer l'allocation.
Il faut donc allouer une chaîne :
char fichier[255]; //ou avec malloc
strcpy(fichier,getenv(...)); //ou encore mieux avec strncpy
strcat(fichier, "\\SHZ_...");
@Char Sniper,
Cela me permet de tout écrire (mes résultats) dans un rapport avec fprintf().
@Fiddy,
Donc,
Dans le 1, il n'y a pas assez de place pour avoir 2. Il faut donc allouer un espace en mémoire c'est ça ?
Pourquoi est-ce mieux d'utiliser strcpy ?
J'ai modifié ainsi:
Et cela passe avec Attributes !
C'était donc ça ! Cependant je pense que je vais encore devoir user un peu de ton temps pour assimiler cela ;-)
Merci,
rapport = fopen("chemin_de_mon_rapport", "w");
Cela me permet de tout écrire (mes résultats) dans un rapport avec fprintf().
@Fiddy,
Donc,
strcat("1","2");
Dans le 1, il n'y a pas assez de place pour avoir 2. Il faut donc allouer un espace en mémoire c'est ça ?
Pourquoi est-ce mieux d'utiliser strcpy ?
J'ai modifié ainsi:
char home[255]; strcpy(home, getenv("HOMEDRIVE")); const char * report_path = strcat(home,"\\SHZ_LookUp.txt");
Et cela passe avec Attributes !
C'était donc ça ! Cependant je pense que je vais encore devoir user un peu de ton temps pour assimiler cela ;-)
Merci,
D'accord merci pour ces réponses, je progresse petit à petit,
Pour sptrinf() je pensais que ça affichait le résultat à l'écran un peu comme printf(), mais visiblement non...
Je suppose qu'avec malloc, on peut attribuer juste ce qu'il faut de mémoire ?
Car ici,
255 me semble élevé, et d'un autre côté je ne veux pas incrémenter manuellement le bazar jusqu'à la bonne valeur :-)
Aussi, j'ai remarqué qu'il y a erreur lorsque je tente d'afficher une chaîne de caractère mal formatée, par exemple en voulant afficher du DWORD avec %s au lieu de %x...
(si ça peut aider quelqu'un)
Merci, ;-)
Pour sptrinf() je pensais que ça affichait le résultat à l'écran un peu comme printf(), mais visiblement non...
Je suppose qu'avec malloc, on peut attribuer juste ce qu'il faut de mémoire ?
Car ici,
char home[255]; strcpy(home, getenv("HOMEDRIVE")); const char * report_path = strcat(home,"\\SHZ_LookUp.txt");
255 me semble élevé, et d'un autre côté je ne veux pas incrémenter manuellement le bazar jusqu'à la bonne valeur :-)
Aussi, j'ai remarqué qu'il y a erreur lorsque je tente d'afficher une chaîne de caractère mal formatée, par exemple en voulant afficher du DWORD avec %s au lieu de %x...
(si ça peut aider quelqu'un)
Merci, ;-)
Pour sptrinf() je pensais que ça affichait le résultat à l'écran un peu comme printf(), mais visiblement non...
La différence entre sprintf et printf est que le premier affiche dans une chaîne (en premier argument) et non à l'écran (fichier stdout). Voilà pourquoi sprintf est approprié ici.
Je suppose qu'avec malloc, on peut attribuer juste ce qu'il faut de mémoire ?
Yes. Encore faut-il connaître la taille. Pour info, on dit "allouer" et non "attribuer" de la mémoire.
255 me semble élevé, et d'un autre côté je ne veux pas incrémenter manuellement le bazar jusqu'à la bonne valeur :-)
Cela ne se fait pas au hasard ^^.
Il suffit de faire :
char *home;
home=malloc(strlen(getenv("HOMEDRIVE"))+strlen("\\SHZ_LookUp.txt")+1);
strcpy(home,getenv("..."));
strcat(home,"\\SHZ...");
Et tu as la bonne taille :-).
Aussi, j'ai remarqué qu'il y a erreur lorsque je tente d'afficher une chaîne de caractère mal formatée, par exemple en voulant afficher du DWORD avec %s au lieu de %x...
Normal. %s c'est pour afficher une chaîne. DWORD n'est pas une chaîne...
La différence entre sprintf et printf est que le premier affiche dans une chaîne (en premier argument) et non à l'écran (fichier stdout). Voilà pourquoi sprintf est approprié ici.
Je suppose qu'avec malloc, on peut attribuer juste ce qu'il faut de mémoire ?
Yes. Encore faut-il connaître la taille. Pour info, on dit "allouer" et non "attribuer" de la mémoire.
255 me semble élevé, et d'un autre côté je ne veux pas incrémenter manuellement le bazar jusqu'à la bonne valeur :-)
Cela ne se fait pas au hasard ^^.
Il suffit de faire :
char *home;
home=malloc(strlen(getenv("HOMEDRIVE"))+strlen("\\SHZ_LookUp.txt")+1);
strcpy(home,getenv("..."));
strcat(home,"\\SHZ...");
Et tu as la bonne taille :-).
Aussi, j'ai remarqué qu'il y a erreur lorsque je tente d'afficher une chaîne de caractère mal formatée, par exemple en voulant afficher du DWORD avec %s au lieu de %x...
Normal. %s c'est pour afficher une chaîne. DWORD n'est pas une chaîne...
D'accord, je vais assimiler tout cela, merci !!
Avant de partir:
Me renvoie:
1>Database.cpp(43): error C2440: 'initialisation' : impossible de convertir de 'void *' en 'char *'
1> La conversion de 'void*' en pointeur vers non 'void' nécessite un cast explicite
Et je n'arrive pas à le caster comme il le faut...
Avant de partir:
char * home; (ligne 43) home = malloc(strlen (getenv("HOMEDRIVE")) + strlen("\\SHZ_LookUp.txt") +1); strcpy(home, getenv("HOMEDRIVE")); const char * report_path = strcat(home, "\\SHZ_LookUp.txt");
Me renvoie:
1>Database.cpp(43): error C2440: 'initialisation' : impossible de convertir de 'void *' en 'char *'
1> La conversion de 'void*' en pointeur vers non 'void' nécessite un cast explicite
Et je n'arrive pas à le caster comme il le faut...
Database.cpp
Ah on en apprend des choses :-). Tu programmes en C++ et non en C.
Ce sont deux langages distincts. Du coup, certaines choses C ne fonctionnent pas en C++ comme la promotion automatique du type void*.
Tu dois donc mettre : (char*) devant le malloc.
Mais, je te conseille plutôt de vraiment programmer en C pour ne pas prendre de mauvaises habitudes ou alors de faire du C++. Dans ce cas, il faudra simplement utiliser l'opérateur new.
Ah on en apprend des choses :-). Tu programmes en C++ et non en C.
Ce sont deux langages distincts. Du coup, certaines choses C ne fonctionnent pas en C++ comme la promotion automatique du type void*.
Tu dois donc mettre : (char*) devant le malloc.
Mais, je te conseille plutôt de vraiment programmer en C pour ne pas prendre de mauvaises habitudes ou alors de faire du C++. Dans ce cas, il faudra simplement utiliser l'opérateur new.
Coucou Fiddy,
Nah, pas de C++ pour le moment, je n'en n'ai pas envie et qui plus est, c'est plein de trucs incompréhensibles à mon niveau !
En fait, je suis sous Visual C++ qui, fait aussi du C.
Je devrais sans doute migrer sous CodeBlocks, mais j'aime bien Visual C++ et m'y suit habitué.
J'ai essayé de caster Malloc, mais ça n'avait pas marché me semble-t-il, je vais regarder cela.
Quel bazar, merci pour votre aide j'ai appris pas mal de choses,
Le C++ c'est pour plus tard, ;-)
Nah, pas de C++ pour le moment, je n'en n'ai pas envie et qui plus est, c'est plein de trucs incompréhensibles à mon niveau !
En fait, je suis sous Visual C++ qui, fait aussi du C.
Je devrais sans doute migrer sous CodeBlocks, mais j'aime bien Visual C++ et m'y suit habitué.
J'ai essayé de caster Malloc, mais ça n'avait pas marché me semble-t-il, je vais regarder cela.
Quel bazar, merci pour votre aide j'ai appris pas mal de choses,
Le C++ c'est pour plus tard, ;-)
Oups, y'a pas mal de choses à modifier et ce n'est pas le top pour moi qui risque de tout péter (j'aime bien trifouiller les réglages).
Je pense laisser ainsi, du toute manière je vais devoir aller vers le C++ un jour prochain alors... :-)
Merci pour votre aide, j'ai beaucoup appris !
A bientôt, ...
Je pense laisser ainsi, du toute manière je vais devoir aller vers le C++ un jour prochain alors... :-)
Merci pour votre aide, j'ai beaucoup appris !
A bientôt, ...