Pregunta

Entonces tengo algo de código C:

#include <stdio.h>
#include <string.h>

/* putting one of the "char*"s here causes a segfault */
void main() {
  char* path = "/temp";
  char* temp;
  strcpy(temp, path);
}

Esto compila, se ejecuta y se comporta como parece.Sin embargo, si uno o ambos punteros de caracteres se declaran como variable global, strcpy produce un error de segmentación.¿Por qué pasó esto?Evidentemente hay un error en mi comprensión del alcance.

¿Fue útil?

Solución

Como mencionaron otros carteles, la raíz del problema es que la temperatura no está inicializada.Cuando se declara como una variable automática en la pila, contendrá cualquier basura que se encuentre en esa ubicación de memoria.Aparentemente, para el compilador+CPU+OS que está ejecutando, la basura en esa ubicación es un puntero válido.El strcpy "tiene éxito" porque no segmenta, pero en realidad copia una cadena en alguna ubicación arbitraria en otra parte de la memoria.Este tipo de problema de corrupción de memoria infunde miedo en los corazones de los programadores de C de todo el mundo, ya que es extraordinariamente difícil de depurar.

Cuando mueve la declaración de la variable temporal al alcance global, se coloca en la sección BSS y se pone a cero automáticamente.Los intentos de eliminar la referencia a *temp resultan en un error de segmentación.

Cuando mueves *ruta al alcance global, *temp sube una ubicación en la pila.La basura en esa ubicación aparentemente no es un puntero válido, por lo que eliminar la referencia a *temp resulta en un error de segmentación.

Otros consejos

La variable temporal no apunta a ningún almacenamiento (memoria) y no está inicializada.

si la temperatura se declara como char temp[32]; entonces el código funcionaría sin importar dónde se declare.Sin embargo, existen otros problemas al declarar temperaturas con un tamaño fijo como ese, pero esa es una pregunta para otro día.

Ahora bien, ¿por qué falla cuando se declara globalmente y no localmente?Suerte...

Cuando se declara localmente, el valor de temp proviene de cualquier valor que pueda estar en la pila en ese momento.Es una suerte que apunte a una dirección que no provoque un bloqueo.Sin embargo, está destruyendo la memoria utilizada por otra persona.

Cuando se declaran globalmente, en la mayoría de los procesadores estas variables se almacenarán en segmentos de datos que utilizarán páginas de demanda cero.De este modo char *temp parece como si hubiera sido declarado char *temp=0.

Olvidaste asignar e inicializar la temperatura:

temp = (char *)malloc(TEMP_SIZE);

Solo asegúrate de que TEMP_SIZE sea lo suficientemente grande.También puedes calcular esto en tiempo de ejecución, luego asegurarte de que el tamaño sea suficiente (debe ser al menos strlen(ruta))

Como se mencionó anteriormente, olvidó asignar espacio para la temperatura.yo prefiero strdup a malloc+strcpy.Hace lo que quieres hacer.

No, esto no funciona independientemente de las variables, simplemente parece que funcionó porque tuviste (des)suerte.Debe asignar espacio para almacenar el contenido de la cadena, en lugar de dejar la variable sin inicializar.

Las variables no inicializadas en la pila apuntarán a ubicaciones de memoria bastante aleatorias.Si estas direcciones resultan ser válidas, su código pisoteará todo lo que haya allí, pero no obtendrá un error (pero puede tener errores desagradables relacionados con la corrupción de la memoria en otras partes de su código).

Los globales fallan constantemente porque generalmente se configuran con patrones específicos que apuntan a memoria no mapeada.Intentar eliminar la referencia a estos genera un error de segmentación inmediatamente (lo cual es mejor: dejarlo para más tarde hace que el error sea muy difícil de rastrear).

Me gustaría reescribir el primer fragmento de Adam como

// Make temp a static array of 256 chars
char temp[256];
strncpy(temp, sizeof(temp), path);
temp[sizeof(temp)-1] = '\0';

De esa manera tú:

1. don't have magic numbers laced through the code, and
2. you guarantee that your string is null terminated.

El segundo punto es la pérdida del último carácter de la cadena de origen si tiene >= 256 caracteres de largo.

La parte importante a tener en cuenta:
la cadena de destino destino debe ser lo suficientemente grande para recibir la copia.
En su situación, Temp no tiene memoria asignada para copiar.

Copiado de la página de manual de strcpy:

DESCRIPTION
   The  strcpy()  function  copies the string pointed to by src (including
   the terminating '\0' character) to the array pointed to by  dest.   The
   strings  may not overlap, and the destination string dest must be large
   enough to receive the copy.

Estás invocando un comportamiento indefinido, ya que no estás inicializando el temp variable.Apunta a una ubicación aleatoria en la memoria, por lo que su programa puede funciona, pero lo más probable es que tenga un error de segmentación.Necesita que su cadena de destino sea una matriz o que apunte a la memoria dinámica:

// Make temp a static array of 256 chars
char temp[256];
strncpy(temp, 256, path);

// Or, use dynamic memory
char *temp = (char *)malloc(256);
strncpy(temp, 256, path);

Además, utilice strncpy() en lugar de strcpy() para evitar desbordamientos del buffer.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top