Fallo de “caída” o “segmentación” cuando los datos se copian / escanean / leen en un puntero sin inicializar

Esta pregunta está destinada a ser utilizada como referencia para todas las preguntas frecuentes de la naturaleza:

¿Por qué obtengo una falla misteriosa o un “fallo de segmentación” cuando copio / escaneo datos a la dirección a la que apunta un puntero sin inicializar?

Por ejemplo:

char* ptr; strcpy(ptr, "hello world"); // crash here! 

o

 char* ptr; scanf("%s", ptr); // crash here! 

Un puntero es un tipo especial de variable, que solo puede contener una dirección de otra variable. No puede contener ningún dato. No puede “copiar / almacenar datos en un puntero”, eso no tiene ningún sentido. Solo puede establecer un puntero para apuntar a los datos asignados en otro lugar.

Esto significa que para que un puntero sea significativo, siempre debe apuntar a una ubicación de memoria válida. Por ejemplo, podría apuntar a la memoria asignada en la stack:

 { int data = 0; int* ptr = &data; ... } 

O memoria asignada dinámicamente en el montón:

 int* ptr = malloc(sizeof(int)); 

Siempre es un error utilizar un puntero antes de que se haya inicializado. Todavía no apunta a una memoria válida.

Todos estos ejemplos podrían provocar fallos en el progtwig u otros tipos de comportamiento inesperado, como “fallas de segmentación”:

 /*** examples of incorrect use of pointers ***/ // 1. int* bad; *bad = 42; // 2. char* bad; strcpy(bad, "hello"); 

En su lugar, debe asegurarse de que el puntero apunte a (suficiente) memoria asignada:

 /*** examples of correct use of pointers ***/ // 1. int var; int* good = &var; *good = 42; // 2. char* good = malloc(5+1); // allocates memory for 5 characters and 1 terminator strcpy(good, "hello"); 

Tenga en cuenta que también puede establecer un puntero para que apunte a un “ningún lugar” bien definido, al dejar que apunte a NULL . Esto lo convierte en un puntero nulo , que es un puntero que garantiza no apuntar a ninguna memoria válida. Esto es diferente de dejar el puntero completamente sin inicializar.

 int* p1 = NULL; // pointer to nowhere int* p2; // uninitialized pointer, pointer to "anywhere", cannot be used yet 

Sin embargo, si intenta acceder a la memoria apuntada por un puntero nulo, puede obtener problemas similares a los de usar un puntero sin inicializar: fallas o fallas de segmentación. En el mejor de los casos, su sistema nota que está intentando acceder a la dirección nula y luego lanza una “excepción de puntero nulo”.

La solución para los errores de excepción de puntero nulo es la misma: debe configurar el puntero para que apunte a la memoria válida antes de usarlo.


Otras lecturas:

Punteros apuntando a datos inválidos
¿Cómo acceder a una variable local desde una función diferente usando punteros?
¿Se puede acceder a la memoria de una variable local fuera de su scope?

Falla de segmentación y causas.
¿Qué es una falla de segmentación?
¿Por qué aparece un error de segmentación al escribir en una cadena inicializada con “char * s” pero no “char s []”?
¿Cuál es la diferencia entre char s [] y char * s?
Lista definitiva de razones comunes para las fallas de segmentación
¿Qué es un error de autobús?

  1. Los punteros solo apuntan a una ubicación de memoria. Creó un puntero pero aún no se ha enlazado a una ubicación de memoria. strcpy quiere que pases dos punteros (el primero no debe ser constante ) que apunten a dos matrices de caracteres como esta firma:

     char * strcpy ( char * destination, const char * source ); 

    uso de la muestra:

     char* ptr = malloc(32); strcpy(ptr, "hello world"); 
     char str[32]; strcpy(str, "hello world"); 
  2. Puede probar el siguiente fragmento de código para leer la cadena hasta alcanzar el carácter de nueva línea (* también puede agregar otros caracteres de espacio en blanco como "%[^\t\n]s" ( tab, nueva línea ) o "%[^ \t\n]s" ( espacio, tabulador, nueva línea )).

     char *ptr = malloc(32); scanf("%31[^\n]", ptr); 

    (En la vida real, ¡no olvide verificar el valor de retorno de scanf() !)

Esto sucede porque no ha asignado memoria para el puntero char* ptr . En este caso, debe asignar dinámicamente memoria para el puntero.

Se pueden usar dos funciones malloc() y calloc() para dynamic memory allocation .

Intente este código: –

  char* ptr; ptr = (char *) malloc(sizeof(char)*50); // allocate space for 50 characters. strcpy(ptr, "hello world"); 

Cuando el uso de *ptr over no olvide desasignar la memoria asignada para *ptr . Esto se puede hacer usando free() función free() .

  free(ptr); // deallocating memory. 

El tamaño de la memoria asignada dinámicamente se puede cambiar utilizando realloc() .

  ptr = (char *)realloc(ptr, sizeof(char)*100);// allocate space for 0 characters. 

En la mayoría de los casos, la “falla de segmentación” ocurre debido a un error en la asignación de memoria o en una matriz fuera de los casos vinculados .