J'ai rendu ce dictionnaire "Vérification orthographique" fonctionne pendant un moment et je l'ai enfin fonctionné entièrement, à l'exception d'une petite erreur de ne pas avoir aucune idée de la fuite de cette mémoire. Quand j'exécute Valgrind, cela revient:
```C //for the universal hash function #define BASE 256 // Represents a node in a hash table typedef struct node { char word[LENGTH + 1]; struct node *next; } node; // Number of buckets in hash table const unsigned int N = 676; // Hash table node *table[N]; int word_count = 0; // Returns true if word is in dictionary else false //Require a search funtion bool check(const char *word) { //change to lower case to compare char low[LENGTH + 1]; for (int i = 0, n = strlen(word); i <= (n + 1); i++) { low[i] = tolower(word[i]); } int hashIndex = hash(low); for (node *tmp = table[hashIndex]; tmp != NULL; tmp = tmp->next) { if (strcasecmp(low, tmp->word) == 0) { return true; } } return false; } // Hashes word to a number // the dividing hash function is one I cited from the yale.edu page http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)HashTables.html having worked with. unsigned int hash(const char *word) { unsigned long m = 11; unsigned long h; unsigned const char *us; //ensure element value is >= 0 us = (unsigned const char *) word; h = 0; while(*us != '\0') { h = (h * BASE + *us) % m; us++; } return (h % N); } // Loads dictionary into memory, returning true if successful else false //Bring the used sictionary to menu asap bool load(const char *dictionary) { // Open file and check file FILE *file = fopen(dictionary, "r"); if (!file) { return false; } //array declaration for fscanf to read into char word[LENGTH + 1]; while (fscanf(file, "%s", word) == 1) { //Create node n = new node node *n = malloc(sizeof(node)); if (n == NULL) { printf("No memory for node\n"); fclose(file); return false; } strcpy(n->word, word); //Hash the word int hashDigit = hash(word); //Insert into the beginning of the list if (table[hashDigit] == NULL) { table[hashDigit] = n; n->next = NULL; } else { n->next = table[hashDigit]; table[hashDigit] = n; } word_count++; } return true; } // Returns number of words in dictionary if loaded else 0 if not yet loaded //count the amount of words in dictionary unsigned int size(void) { return word_count; } // Unloads dictionary from memory, returning true if successful else false //free the dictionary from memory asap bool unload(void) { //Loop to run through array for (int i = 0; i < N; i++) { //to target linked list while (table[i] != NULL) { node *tmp = table[i]; table[i] = table[i]->next; free(tmp); } } return true; }
4 Réponses :
Il fuit Ceci est où fichier * code> obtenu de
fopen code>.
FCLOSE CODE> est manquant.
Valgrind code> vous indique que: p>
fopen Code> Finalement appelle
MALLOC CODE> pour allouer ce fichier
code> qui doit être publié avec
FCLOSE code> qui appelle éventuellement
gratuit code> sur ce fichier * code>. p>
saut conditionnel ou déplacement dépend de la valeur non initialisée code> Avertissement est causée par: P>
for (int i = 0, n = strlen(word); i <= (n + 1); i++)
low[i] = tolower(word[i]);
Cela m'est venu que le commentaire final de l'utilisateur est exactement ce que je pourrais retirer sur ma première expérience de Valgrind. Remarquez à quel point les avertissements non initialisés sont-ils éminents que les informations de la mémoire de la mémoire? Je pense que vous devriez mentionner cela dans votre réponse, car si les avertissements de fuite de la mémoire utilisaient dans la sortie avant de résoudre ceux-ci, il peut encore avoir cela "voir texte de la promotion et répondre" habitude.
Je ne sais pas comment interpréter votre réponse principalement car il applique mon point sur la possibilité que l'utilisateur ait pu créer une habitude de réponse à ce qu'il lisait de la manière que vous suggérez. En d'autres termes, s'il veut d'abord se débarrasser de toutes les fuites de mémoire, il devra sauter la partie supérieure que nous voyons tous maintenant ici.
J'ai essayé cette solution, mais il ne semble pas que cela me dise qu'ici:
@Kwsswart a mis à jour la réponse pour vous.
== 707 == Le saut conditionnel ou le déplacement dépend de la valeur non initialisée == 707 == à 0x520A60F: tolower (CTYPE.c: 46) == 707 == par 0x4010E2: chèque (Dictionary.c: 37) == 707 == par 0x400cd9: Main (Spoverer.c: 112) == 707 == Valeur non initialisée a été créée par une allocation de pile == 707 == à 0x4008E4: principale (orthographe.c: 21) == 707 == utilisation de Valeur non initialisée de la taille 8 == 707 == à 0x520A623: tolower (ctype.c: 46) == 707 == par 0x4010e2: chèque (Dictionary.c: 37) == 707 == par 0x400CD9: Main (Speler.C : 112) == 707 == La valeur non initialisée a été créée par une répartition de la pile
@ Maxim Egorushkin merci beaucoup, une fois de plus, j'ai commis l'erreur de courir une boucle une fois de loin
@Kwsswart: Il n'y a vraiment que 2 choses difficiles dans la programmation: nommer des choses, la mise en cache et les erreurs obsolètes.
> ==793== 552 bytes in 1 blocks are still reachable in loss record 1 of 1 > ==793== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) > ==793== by 0x5258E49: __fopen_internal (iofopen.c:65) > ==793== by 0x5258E49: fopen@@GLIBC_2.2.5 (iofopen.c:89) > ==793== by 0x401211: load (dictionary.c:77) > ==793== by 0x4009B4: main (speller.c:40) The leak is coming from fopen because you aren't calling fclose.
J'ai essayé cela, mais cela ne semble pas complètement arrêter les lignes ...
== 707 == Le saut conditionnel ou le déplacement dépend de la valeur non initialisée == 707 == à 0x520A60F: tolower (CTYPE.c: 46) == 707 == par 0x4010E2: chèque (Dictionary.c: 37) == 707 == par 0x400CD9: Main (Spoverer.c: 112) == 707 == La valeur non initialisée a été créée par une allocation de pile == 707 == == 707 == Utilisation de la valeur non initialisée de la taille 8 == 707 == à 0x520a623: tolower (ctype.c: 46) == 707 == par 0x4010e2: chèque (Dictionary.c: 37) == 707 == par 0x400CD9: Main (orthographe.c: 112) == 707 == Valeur non initialisée était Créé par une allocation de pile == 707 == à 0x4008E4: Main (Speller.c: 21)
Vous faites un grand nombre de pointeurs ici mais vous ne définissez jamais ce tableau à NULL. p> alors vous faites toutes sortes de choses sur ce tableau en supposant que a été initialisé. p> p>
Le vrai problème est qu'il s'agit d'une matrice de longueur variable déclarée à la portée mondiale.
S'il s'agissait d'une matrice de taille statique appropriée à l'aide d'une valeur constante vraie (plutôt que d'un const code>), je pense que cela devrait suivre les règles de la durée de stockage statique des objets déclarés, auquel cas les éléments seraient implicitement initialisé à NULL par norme C11 6.7.9 P10
@Christiangibbbons - Je n'étais pas sûr de quelle version il utilisait: haussement d'épaules:
Je ne crois pas que la version devrait importer; Les mêmes règles doivent s'appliquer. La seule différence étant que les VLAS sont facultatives en C11, obligatoire en C99 et inexistantes en C89, mais dans tous les cas, ils ne sont pas autorisés pour des objets de duration statique de stockage.
@Christiangbbbures - En d'autres termes, c'était différent dans chacune de ces versions? :)
VLAS à la durée de stockage statique n'a été inexistante dans chacune de ces versions et pointesR avec une durée de stockage statique sans initialiseur serait initialisée à NULL pour chacune de ces versions. Donc, pour tout ce qui concerne cela spécifiquement, il ne devrait y avoir aucune différence.
J'avais le même problème avec le même problème (la semaine 5 du cours CS50 de Harvard), mais les réponses ci-dessus ne me sont pas que la moitié du chemin là-bas.
a finalement résolu en attribuant explicitement l'attribution explicitement le terminateur null '\ 0 'Pour les caractères restants de chaque mot, comme: p>
Lorsque vous collez du texte pré-formaté (y compris le code) dans votre message, vous pouvez facilement conserver ce format en sélectionnant ce texte, puis cliquez sur le bouton
{} code>.
Ce code compile? Je vois une matrice de longueur variable globalement scopée.