C - Segmentation Fault avec strcmp?
Je semble être une erreur de segmentation quelque part avec la fonction strcmp.
Je suis encore très novice en C et je ne vois pas pourquoi il me donne l'erreur.
int linear_probe(htable h, char *item, int k){
int p;
int step = 1;
do {
p = (k + step++) % h->capacity;
}while(h->keys[p] != NULL && strcmp(h->keys[p], item) != 0);
return p;
}
gdb:
Program received signal SIGSEGV, Segmentation fault.
0x0000003a8e331856 in __strcmp_ssse3 () from /lib64/libc.so.6
(gdb) frame 1
#1 0x0000000000400ea6 in linear_probe (h=0x603010, item=0x7fffffffde00 "ksjojf", k=-1122175319) at htable.c:52
Edit: insertion code et htable struct
int htable_insert(htable h, char *item){
unsigned int k = htable_word_to_int(item);
int p = k % h->capacity;
if(NULL == h->keys[p]){
h->keys[p] = (char *)malloc(strlen(item)+1);
strcpy(h->keys[p], item);
h->freqs[p] = 1;
h->num_keys++;
return 1;
}
if(strcmp(h->keys[p], item) == 0){
return ++h->freqs[p];
}
if(h->num_keys == h->capacity){
return 0;
}
if(h->method == LINEAR_P) p = linear_probe(h, item, k);
else p = double_hash(h, item, k);
if(NULL == h->keys[p]){
h->keys[p] = (char *)malloc(strlen(item)+1);
strcpy(h->keys[p], item);
h->freqs[p] = 1;
h->num_keys++;
return 1;
}else if(strcmp(h->keys[p], item) == 0){
return ++h->freqs[p];
}
return 0;
}
struct htablerec{
int num_keys;
int capacity;
int *stats;
char **keys;
int *freqs;
hashing_t method;
};
Grâce
Edit: valgrind - moi entrer des valeurs aléatoires à ajouter à la table
sdkgj
fgijdfh
dfkgjgg
jdf
kdjfg
==25643== Conditional jump or move depends on uninitialised value(s)
==25643== at 0x40107E: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643==
fdkjb
kjdfg
kdfg
nfdg
lkdfg
oijfd
kjsf
vmf
kjdf
kjsfg
fjgd
fgkjfg
==25643== Invalid read of size 8
==25643== at 0x400E0E: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x4c342a0 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643== Invalid read of size 8
==25643== at 0x400E2B: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x4c342a0 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643== Invalid read of size 1
==25643== at 0x4A06C51: strcmp (mc_replace_strmem.c:426)
==25643== by 0x400E3C: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x210 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643==
==25643== Process terminating with default action of signal 11 (SIGSEGV)
==25643== Access not within mapped region at address 0x210
==25643== at 0x4A06C51: strcmp (mc_replace_strmem.c:426)
==25643== by 0x400E3C: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== If you believe this happened as a result of a stack
==25643== overflow in your program's main thread (unlikely but
==25643== possible), you can try to increase the size of the
==25643== main thread stack using the --main-stacksize= flag.
==25643== The main thread stack size used in this run was 8388608.
==25643==
==25643== HEAP SUMMARY:
==25643== in use at exit: 1,982 bytes in 28 blocks
==25643== total heap usage: 28 allocs, 0 frees, 1,982 bytes allocated
==25643==
==25643== LEAK SUMMARY:
==25643== definitely lost: 0 bytes in 0 blocks
==25643== indirectly lost: 0 bytes in 0 blocks
==25643== possibly lost: 0 bytes in 0 blocks
==25643== still reachable: 1,982 bytes in 28 blocks
==25643== suppressed: 0 bytes in 0 blocks
==25643== Rerun with --leak-check=full to see details of leaked memory
==25643==
==25643== For counts of detected and suppressed errors, rerun with: -v
==25643== Use --track-origins=yes to see where uninitialised values come from
==25643== ERROR SUMMARY: 7 errors from 4 contexts (suppressed: 6 from 6)
Segmentation fault (core dumped)
static unsigned int htable_word_to_int(char *word){
unsigned int result = 0;
while(*word != '\0'){
result = (*word++ + 31 * result);
}
return result;
}
Est-il réussi à avoir passé l'instruction print? Êtes-vous sûr que votre chaîne est null?
Soit
Vous avez posté une GDB extrait de code, mais ce n'est pas suffisant. Une suggestion serait d'aller à la frame de pile que a code et commencer à fouiller.
Désolé d'être de nouveau à C, mais comment pourrais-je aller sur le faire?
#asveikau: je pense que je l'ai eu. Vérifier modifier sous gdb extrait. Mais même si mon k est négatif, n'est-ce pas p de garantie des valeurs positives en raison de la mod?
Soit
h->keys[p]
ou item
est un pointeur non valide. Il va l'aider à exécuter ce sous un débogueur, de cette façon, vous pouvez imprimer les valeurs de ces au point de défaillance.Vous avez posté une GDB extrait de code, mais ce n'est pas suffisant. Une suggestion serait d'aller à la frame de pile que a code et commencer à fouiller.
Désolé d'être de nouveau à C, mais comment pourrais-je aller sur le faire?
#asveikau: je pense que je l'ai eu. Vérifier modifier sous gdb extrait. Mais même si mon k est négatif, n'est-ce pas p de garantie des valeurs positives en raison de la mod?
OriginalL'auteur rtheunissen | 2011-09-06
Vous devez vous connecter pour publier un commentaire.
En dehors de la possibilité que les valeurs dans votre
htable
peut-être des pointeurs invalides (c'est à dire, ni NULLE, ni un pointeur vers un décent chaîne C), vous avez une grave problème de la présence d'une boucle infinie si elle ne contient ni NULL, ni la chaîne que vous recherchez.Dans l'immédiat le problème, essayez de modifier le code pour:
Ces instructions de débogage devrait vous donner une indication quant à ce qui va mal.
Depuis que vous obtenez:
juste avant le crash, il est évident que quelqu'un est en train de passer dans un bidon de valeur pour
k
. Le modulo de l'opération sur les nombres négatifs est mise en œuvre définies dans la norme C de sorte que vous obtenez une valeur négative pourpos
. Et depuish->pos[-30]
va être un comportement indéterminé, tous les paris sont éteints.Soit de rechercher et de corriger le code en passant que le faux valeur (probablement une variable non initialisée) ou de protéger votre fonction en train de changer:
dans:
au début de votre fonction. J'avais fait faire les deux, mais ensuite, je suis assez parano 🙂
Et, sur la base encore un autre mise à jour (la clé de hachage de calcul, si vous générez un
unsigned int
et puis aveuglément l'utiliser comme un signéint
, vous avez une bonne chance d'obtenir des valeurs négatives:Ce sorties:
Ma suggestion est d'utiliser des entiers non signés pour des valeurs qui sont clairement destinés à être signés.
Votre
k
est corrompu. Voir ma mise à jour.Hé, je suis le paranoïaque ici. 😛 Mais de toute façon, je reçois le k à partir d'une fonction qui modifie une chaîne à un indice. Bas de post-édition, pourriez-vous prendre un coup d'oeil s'il vous plaît?
Premier appel de fonction en haut de la htable_insert fonction, prend la valeur de k et le transmet à linear_probe inchangée.
vous pouvez penser à l'aide de
unsigned
ints partout. La loi de calcul d'un unsigned int en l'affectant à un int peut être problématique. Voir mon autre mise à jour.OriginalL'auteur paxdiablo
Si vous êtes sur linux, essayez de valgrind. Il peut vous dire sur les accès invalides, des fuites de mémoire, les variables non initialisées, etc. La sortie peut sembler confus et difficile à lire, mais si vous continuez à essayer, il vous récompensera. Ce qui se passe:
-g
passer à inclure les informations de débogagevalgrind ./myprogram
Comme je l'ai dit, la sortie peut sembler très salissant, donc peut-être d'abord essayer quelques un programme simple (plaine de la main vide) pour voir à quoi ça ressemble quand tout est ok, alors essayez délibérément de plantage de votre programme, comme:
et voir le résultat.
Une belle introduction de base avec des exemples peuvent être trouvés ici.
Que vous avez fourni valgrind sortie, je voudrais commencer à résoudre les problèmes qui y sont énumérés. D'abord le
Conditional jump or move depends on uninitialised value(s)
erreur. Vous pouvez relancer avec valgrind--track-origins=yes
comme valgrind suggère pour voir plus de détails, puis le fixer (vous n'avez pas les numéros de ligne dans les extraits de code, je ne peux pas vous aider plus).Puis le
Invalid read of size 1
d'erreur signifie que vous avez déjà accès à de la mémoire qui n'est pas la vôtre, mais la lecture de ce que, de sorte qu'il "n'a pas l'esprit". Mais c'est encore une erreur qui ne devrait pas arriver, donc, fixer (si ce n'est pas fixée par la première erreur fix).Et enfin, la
Access not within mapped region
est une écriture de la mémoire qui n'est pas allouée.Maintenant essayer de corriger les erreurs (dans l'ordre valgrind listes d'entre eux) à la suite de valgrind suggestions (comme reruning avec les interrupteurs).
OriginalL'auteur Adam Trhon
bien vous n'avez pas inclure le code autour de htable autour de la garniture, cette table de hachage etc.
strcmp probablement segfaulted parce que soit vous a donné un NUL chaîne de caractères ou un tableau de caractères n'est pas correctement se terminant par un 0....
OriginalL'auteur Friedrich
Est h->touches complètement initialisé avec des valeurs Null? Sinon vous avez des pointeurs à l'intérieur.
BTW,
Toujours vérifier le retour d'une fonction pour la validité s'il signale une erreur, peu importe combien peu probable que l'erreur de cas.
malloc()
retourne NULL en cas d'échec.OriginalL'auteur Secure
Au premier coup d'œil, je pense que ton erreur vient de
p
- vous n'êtes jamais à l'initialisation de cette variable, de sorte qu'il n'est pas garanti pour commencer à zéro; il pourrait commencer à-123456
pour tout ce que vous savez, et puis vous seriez d'accéder à une adresse mémoire non valide. EDIT: mal lu le do-while. Ignorer ce paragraphe.Au deuxième coup d'œil, je voudrais vérifier si
h->keys[p]
est une chaîne se terminant par null -strcmp
va sur la lecture des valeurs jusqu'à ce qu'il frappe un zéro octet, si il n'y a pas d'octets, il peut continuer jusqu'à ce qu'il frappe une adresse mémoire non valide.do
boucle.Cette décision si elle est immédiatement remplacé de toute façon?
arzenik: il n'a pas l'initialiser, mais affecter une valeur (dans la boucle) avant l'utilisation de la variable (dans la terminaison de la boucle)
Ah, my bad. Ma deuxième préoccupation tient toujours; ce n'
h->keys[p]
ressembler?Cochez la case modifier si vous le souhaitez. 🙂
OriginalL'auteur azernik