Mi implementación de strcat(char*, const char*)
parece funcionar, pero luego provoca un volcado del núcleo.
strcat()
implementación:
char* strcat(char* dest, const char* src)
{
char* tmp = dest;
while(*tmp) ++tmp ;
while( (*tmp++ = *src++ ) != '\0') ;
return (dest);
}
Código en int main()
donde llamo strcat():
char arr3[] = "Mr. ";
char arr4[] = "Smith";
printf("Hello %s!", strcat(arr3, arr4));
En realidad, concatenó ambas cadenas y las imprimió, pero aun así provocó un volcado del núcleo.
producción : ¡Hola, Sr. Smith! Abortado (núcleo descargado)
¿Qué hice mal?
Tu programa haciendo desbordamiento de búfer en tiempo de ejecución, por strcat(arr3, arr4)
porque arr3
el tamaño es igual a la longitud de "Mr."
string , no tiene espacio de memoria adicional para caracteres adicionales (de arr4
).
tamaño de arr3
debe tener al menos una longitud de cadena de un "Mr. " + "Smith" + 1
(1 adicional para terminación de cadena \0
carbonizarse)
Mi sugerencia es usar la asignación de memoria dinámica para un búfer de tamaño suficiente, haga algo como el código a continuación:
char arr3[] = "Mr. ";
char arr4[] = "Smith";
length = strlen(arr3) + strlen(arr4) + 1; //cal-length (sufficient long buffer)
char* new_arr = malloc(length); // allocate memory
strcpy(new_arr, arr3); // copy first string
strcat(new_arr, arr4); // then check your function to concat strings
Motivo del volcado de núcleo:
En tu código:
char arr3[] = "Mr. ";
La talla de arr2
es = longitud de la cadena "Mr."
longitud + 1
(1 por \0
) caracteres. los strcat()
primeros movimientos temp
punteros para apuntar nulo en el primer ciclo while while(*tmp) ++tmp ;
.
Después de eso en el segundo bucle while while( (*tmp++ = *src++ ) != '\0') ;
está intentando acceder y asignar una memoria que no está asignada (es posible que esté fuera de su control de proceso) y acceder a una memoria que no ha asignado es un comportamiento indefinido en C.
Editar:
En codigo arr3
es algo como a continuación en el diagrama, donde temp
puntos a arr3
formación:
arr3
temp 5 6 7 8
+-----+ +--+--+--+---+
| 5 +----->|M |r |. |\0 |
+-----+ +--+--+--+---+
cuando bucle while(*tmp) ++tmp ;
descansos temp
comienza a apuntar a la ubicación de la memoria 8
donde nulo \0
se almacena, como el siguiente diagrama.
arr3
temp 5 6 7 8
+-----+ +--+--+--+---+
| 8 | |M |r |. |\0 |
+-----+ +--+--+--+---+
| ^
+--------------------|
Cuando tu lo hagas temp++
en bucle while( (*tmp++ = *src++ ) != '\0') ;
, temp
incremento para apuntar a la ubicación de la memoria 9
y en adelante, pero acceso y asignación en la memoria 9
, 10
.. es ilegal porque no está asignado. Esto hace que el kernel del sistema operativo envíe una señal volcado de memoria al proceso que causó la excepción. (interesante notar: ya que el sistema operativo detecta una violación de los derechos de memoria por parte de un proceso: un acceso no válido a una memoria válida da: SIGSEGV y el acceso a una dirección no válida da: SIGBUS).
Señales de error del programa:
Cuando una de estas señales de error de programa termina un proceso, también escribe un archivo de volcado central que registra el estado del proceso en el momento de la terminación. El archivo de volcado del núcleo se llama ‘core’ y está escrito en cualquier directorio que esté actual en el proceso en ese momento. (En el sistema GNU, puede especificar el nombre de archivo para los volcados del núcleo con la variable de entorno COREFILE). El propósito de los archivos de volcado del núcleo es que pueda examinarlos con un depurador para investigar la causa del error.
Si asigna memoria adicional (como sugirieron @JerryCoffin y @Paul R), entonces puede acceder a la memoria más allá \0
(ubicación de la memoria 8
) no es problema.
Nota: Si no da el tamaño en la declaración, el tamaño de la matriz será igual al tamaño de la cadena, por ejemplo, en char arr3[] = "Mr. ";
el tamaño es 5
. Pero si das el tamaño explícitamente como char arr3[84] = "Mr. ";
entonces el tamaño de aar3
sera 84
y la memoria inicial contiene Mr.
luego 0
en el resto de todas las localidades.
En mi solución, asigno completamente nuevos bloques de memoria que son tan grandes como ambas cadenas arr3
y arr4
se puede almacenar con un símbolo nulo utilizando la asignación de memoria dinámica (malloc()
función). Además, si asigna memoria dinámica usando ptr = malloc()
o ptr = calloc()
entonces deberías liberar memoria explícitamente cuando termines el trabajo usando free(ptr)
.
No ha asignado ningún espacio adicional en str3
así que intentar agregar caracteres usando strcat
desbordará el almacenamiento asignado; cambie su código a, por ejemplo:
char arr3[80] = "Mr. "; // <<< allocate additional storage for appending more characters
char arr4[] = "Smith";
printf("Hello %s!", strcat(arr3, arr4));
El problema no es con tu strcat
, pero con la forma en que lo está usando/invocando. Está escribiendo más allá del final de la matriz de destino.
Cambiar arr3
a algo como char arr3[32] = "Mr. ";
y todo estará bien.
Aunque es antiguo y ha aceptado, pero leyó la respuesta actualizada, agregó algunos detalles interesantes …
–Grijesh Chauhan
08/07/2013 a las 18:15
Bien gracias. Lo haré en unos segundos 😉
– Davlog
12 de julio de 2013 a las 15:36
Probablemente se deba a que cuando no especifica un tamaño, la matriz elige automáticamente el tamaño ideal para adaptarse a su contenido. Entonces
arr3
tiene 5 bytes de largo, y agregando"Smith"
requiere una cadena de 10 bytes. Por qué es un volcado del núcleo en lugar de una falla de segmentación, no puedo decirle.– Braden Mejor
3 de enero de 2016 a las 23:54