Violación de acceso a la memoria. ¿Qué hay de malo con este progtwig aparentemente simple?

Este es un progtwig rápido que escribí para ver si incluso recordé cómo iniciar un progtwig c ++ desde cero. Solo está invirtiendo una cadena (en su lugar), y en general me parece correcta. ¿Por qué no funciona esto?

#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 cambia esto, lo que convierte a someString un puntero a un literal de cadena de solo lectura:

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

a esto, lo que convierte a someString una matriz modificable de caracteres, inicializada desde un literal de cadena:

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

Deberías tener mejores resultados.

Mientras que el tipo de someString en el código original ( char* ) permite la modificación de los caracteres a los que apunta, porque en realidad estaba apuntando a una cadena literal (que no se puede modificar) intentando realizar cualquier modificación a través del puntero dio como resultado lo que técnicamente se conoce como comportamiento indefinido , que en su caso fue una violación de acceso a la memoria.

Si esto no es tarea, la etiqueta C ++ exige que hagas esto utilizando la biblioteca estándar de C ++:

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

Oh, y es int main() , siempre int main() , maldita sea!

Está intentando modificar una cadena literal, una cadena asignada en el almacenamiento estático. Eso es un comportamiento indefinido (normalmente falla el progtwig).

Debería asignar memoria y copiar el literal de cadena allí antes de invertir, por ejemplo:

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

La línea

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

hace que someString apunte a una cadena literal, que no se puede modificar. En lugar de usar un puntero en bruto, use una matriz de caracteres:

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

No puedes cambiar los literales de cadena (asignados estáticamente). Para hacer lo que quieras, necesitas usar algo como:

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

[edit] strdup también funciona, también strncpy … estoy seguro de que hay una variedad de otros métodos 🙂

Ver sharptooth para la explicación.

Intenta esto en su lugar:

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

Mejor aún, olvídate de char * y usa lugar. Esto es C ++, no C, después de todo.

Cuando se usan configuraciones de comstackdor más estrictas, este código ni siquiera debería comstackr:

 char* str = "Constant string"; 

porque debería ser constante:

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

Esto te permite atrapar estos errores más rápido. O simplemente puedes usar una matriz de caracteres:

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

Para estar perfectamente seguro, solo usa std :: string. Después de todo, estás usando C ++, y la manipulación de cadenas sin formato es extremadamente propensa a errores.