Esta pregunta está destinada a ser utilizada como referencia para todas las preguntas frecuentes de la naturaleza:
¿Por qué recibo un bloqueo misterioso o una “falla de segmentación” cuando copio/escaneo datos a la dirección a la que apunta un puntero no inicializado?
Por ejemplo:
char* ptr;
strcpy(ptr, "hello world"); // crash here!
o
char* ptr;
scanf("%s", ptr); // crash here!
Una situación que ocurre con frecuencia mientras se aprende C es tratar de usar comillas simples para denotar un literal de cadena:
char ptr[5];
strcpy(ptr, 'hello'); // crash here!
// ^ ^ because of ' instead of "
Cª, 'h'
es un literal de un solo carácter, mientras que "h"
es un literal de cadena que contiene un 'h'
y un terminador nulo \0
(es decir, una matriz de 2 caracteres). Además, en C, el tipo de un carácter literal es int
es decir, sizeof('h')
es equivalente a sizeof(int)
mientras sizeof(char)
es 1
.
char h="h";
printf("Size: %zu\n", sizeof(h)); // Size: 1
printf("Size: %zu\n", sizeof('h')); // likely output: Size: 4
Esto sucede porque tienes no asignado memoria para el puntero char* ptr
. En este caso tienes que asignar dinámicamente memoria para el puntero.
Dos funciones malloc()
y calloc()
se puede utilizar para dynamic memory allocation
.
Prueba este código: –
char* ptr;
ptr = malloc(50); // allocate space for 50 characters.
strcpy(ptr, "hello world");
Cuando el uso de *ptr
terminado no te olvides de desasignar memoria asignado para *ptr
.Esto se puede hacer usando free()
función.
free(ptr); // deallocating memory.
Tamaño de memoria asignada dinámicamente se puede cambiar usando realloc()
.
char *tmp = realloc(ptr, 100); // allocate space for 100 characters.
if (! tmp) {
// reallocation failed, ptr not freed
perror("Resize failed");
exit(1);
}
else {
// reallocation succeeded, old ptr freed
ptr = tmp;
}
En la mayoría de los casos “Fallo de segmentación” ocurre debido a un error en asignación de memoria o matriz fuera de límite casos.
Para hacer una copia modificable de una cadena, en lugar de usar malloc
, strlen
y strcpy
la biblioteca POSIX C tiene una función útil llamada strdup
en <string.h>
que devolverá una copia de la cadena terminada en nulo pasada con la duración de almacenamiento asignada. Después de su uso, el puntero debe soltarse con free
:
char* ptr;
ptr = strdup("hello world");
ptr[0] = 'H';
puts(ptr);
free(ptr);
El problema es más que los OP ni siquiera saben que el puntero no está inicializado, pero que mágicamente aparece un objeto una vez que declaras/defines (también confunden esto) puntero.
– demasiado honesto para este sitio
31 de mayo de 2016 a las 15:21
Probablemente debería cambiar el título si desea que esta pregunta sea leída por aquellos que experimentan este problema. antes de lo publican aquí.
– barak manos
31 de mayo de 2016 a las 15:22
@Olaf De hecho, entonces usted cierra la votación de sus preguntas de segmentación como duplicados con un enlace a este. Siempre me he estado perdiendo una pregunta de preguntas frecuentes como esta; finalmente pude escribir uno.
– Lundin
31 de mayo de 2016 a las 15:22
@barakmanos La intención es usar esta publicación como un “duplicado canónico” para preguntas frecuentes. Realmente no espero que los novatos lo encuentren por sí mismos.
– Lundin
31 de mayo de 2016 a las 15:23
@Lundin: Aprecio tu esfuerzo. Si eso se entiende como un dup-CV, estoy contigo. Pero en realidad preferiría que lo encontraran ellos mismos antes de publicarlo. Pero entonces esto probablemente sea una ilusión de todos modos, ya que los principiantes tienden a pensar que su problema es único. Entonces, tenga +1 y lo tendré en cuenta, ¡gracias!
– demasiado honesto para este sitio
31 mayo 2016 a las 15:25