
Cemre Mengü
Tengo este código en C que toma un montón de char
s
#include<stdio.h>
# define NEWLINE '\n'
int main()
{
char c;
char str[6];
int i = 0;
while( ((c = getchar()) != NEWLINE))
{
str[i] = c;
++i;
printf("%d\n", i);
}
return 0;
}
La entrada es: testtesttest
Salida: 1 2 3 4 5 6 7 8 117 118 119 120
Mis preguntas son:
-
¿Por qué no obtengo una excepción fuera de los límites (falla de segmentación) aunque excedo claramente la capacidad de la matriz?
-
¿Por qué los números en la salida saltan repentinamente a números muy grandes?
Intenté esto en C++ y obtuve el mismo comportamiento. ¿Alguien podría explicar cuál es la razón de esto?

jackman
Tienes que compilar así:
gcc -fsanitize=address -ggdb -o test test.c
Hay más información aquí.
Escribir fuera de los límites de la matriz (en realidad, incluso simplemente realizar la aritmética del puntero/subíndice de la matriz, incluso si no usa el resultado para leer o escribir nada) da como resultado comportamiento indefinido. El comportamiento indefinido no es un error notificado o notificable; significa que su programa podría hacer cualquier cosa. Es muy peligroso y usted es completamente responsable de evitarlo. C no es Java/Python/etc.

Max E.
La asignación de memoria es más complicada de lo que parece. La variable “str”, en este caso, está en la pila, junto a otras variables, por lo que no la sigue la memoria no asignada. La memoria también suele estar alineada con palabras (una “palabra” tiene entre cuatro y ocho bytes). Posiblemente estaba jugando con el valor de otra variable, o con algún “relleno” (espacio vacío agregado para mantener la alineación de palabras) o algo completamente diferente. .
Como dijo R.., es un comportamiento indefinido. Las condiciones fuera de los límites podrían causar un error de segmento… o podrían causar una corrupción silenciosa de la memoria. Si está modificando la memoria que ya se ha asignado, el sistema operativo no lo detectará. Es por eso que los errores fuera de los límites son tan insidiosos en C.
Cuando accede a un índice de matriz, C y C ++ no realizan una verificación de límites. Las fallas de segmentación solo ocurren cuando intenta leer o escribir en una página que no estaba asignada (o intenta hacer algo en una página que no está permitida, por ejemplo, intenta escribir en una página de solo lectura), pero dado que las páginas generalmente son bastante grande (múltiplos de unos pocos kilobytes; en Mac OS, múltiplos de 4 KB), a menudo deja mucho espacio para desbordarse.
Si su matriz está en la pila (como la suya), puede ser aún peor ya que la pila suele ser bastante grande (hasta varios megabytes). Esta es también la causa de los problemas de seguridad: escribir más allá de los límites de una matriz en la pila puede sobrescribir la dirección de retorno de la función y provocar la ejecución de código arbitrario (las famosas infracciones de seguridad de “desbordamiento de búfer”).
Los valores que obtienes cuando lees son simplemente lo que existe en este lugar en particular. Ellos son completamente indefinido.
Si usa C++ (y tiene la suerte de trabajar con C++11), el estándar define el std::array<T, N>
type, que es una matriz que conoce sus límites. Él at
arrojará si intenta leer más allá del final.
Posible duplicado de Acceder a una matriz fuera de los límites no da error, ¿por qué?, ¿Qué tan peligroso es acceder a una matriz fuera de los límites?, etc.
– jww
4 de octubre de 2019 a las 11:53