Violation d’access mémoire. Quel est le problème avec ce programme apparemment simple?

C’est un programme rapide que je viens d’écrire pour voir si je me souvenais même comment démarrer un programme c ++ à partir de zéro. Il s’agit simplement d’inverser une chaîne (en place) et me semble généralement correct. Pourquoi ça ne marche pas?

#include  using namespace std; void strReverse(char *original) { char temp; int i; int j; for (i = 0, j = strlen(original) - 1; i < j; i++, j--) { temp = original[i]; original[i] = original[j]; original[j] = temp; } } void main() { char *someString = "Hi there, I'm bad at this."; strReverse(someString); } 

Si vous modifiez cela, cela fera de someSsortingng un pointeur sur un littéral de chaîne en lecture seule:

 char *someSsortingng = "Hi there, I'm bad at this."; 

à cela, qui fait de someSsortingng un tableau modifiable de char , initialisé à partir d’un littéral de chaîne:

 char someSsortingng[] = "Hi there, I'm bad at this."; 

Vous devriez avoir de meilleurs résultats.

Tandis que le type de someSsortingng dans le code d’origine ( char* ) permet de modifier les caractères qu’il pointe, car il pointait en fait sur un littéral de chaîne (qu’il n’est pas permis de modifier) ​​en essayant de modifier le pointeur. a entraîné ce qui est techniquement connu sous le nom de comportement indéfini , qui dans votre cas était une violation d’access à la mémoire.

S’il ne s’agit pas d’un devoir, la balise C ++ vous le demande en utilisant la bibliothèque standard C ++:

 std::ssortingng s("This is easier."); std::reverse(s.begin(), s.end()); 

Oh, et c’est int main() , toujours int main() , bon sang!

Vous essayez de modifier un littéral de chaîne – une chaîne allouée dans un stockage statique. C’est un comportement indéfendable (bloque généralement le programme).

Vous devez allouer de la mémoire et copier le littéral chaîne avant de procéder à l’inversion, par exemple:

 char *someSsortingng = "Hi there, I'm bad at this."; char* ssortingngCopy = new char[strlen( someSsortingng ) + 1]; strcpy( ssortingngCopy, someSsortingng ); strReverse( ssortingngCopy ); delete[] ssortingngCopy;//deallocate the copy when no longer needed 

La ligne

 char *someSsortingng = "Hi there, I'm bad at this."; 

fait pointer someSsortingng vers un littéral de chaîne, qui ne peut pas être modifié. Au lieu d’utiliser un pointeur brut, utilisez un tableau de caractères:

 char someSsortingng[] = "Hi there, I'm bad at this."; 

Vous ne pouvez pas modifier les littéraux de chaîne (alloués de manière statique). Pour faire ce que vous voulez, vous devez utiliser quelque chose comme:

 int main() { char *str = new char[a_value]; sprintf(str, "%s", ); strReverse(str); delete [] str; return 0; } 

[edit] strdup fonctionne aussi, mais aussi strncpy … je suis sûr qu’il existe une variété d’autres méthodes 🙂

Voir sharptooth pour l’explication.

Essayez ceci à la place:

 #include  void main() { char someSsortingng[27]; std::strcpy( someSsortingng, "Hi there, I'm bad at this." ); strReverse( someSsortingng ); } 

Mieux encore, oubliez char * et utilisez plutôt . C’est C ++, pas C, après tout.

Lorsque vous utilisez des parameters de compilateur plus ssortingcts, ce code ne devrait même pas comstackr:

 char* str = "Constant ssortingng"; 

parce qu’il devrait être constant:

 const char* str = "Now correct"; const char str[] = "Also correct"; 

Cela vous permet de détecter ces erreurs plus rapidement. Ou vous pouvez simplement utiliser un tableau de caractères:

 char str[] = "You can write to me, but don't try to write something longer!"; 

Pour être parfaitement en sécurité, utilisez simplement std :: ssortingng. Après tout, vous utilisez C ++ et la manipulation de chaîne brute est extrêmement sujette aux erreurs.