¿Qué tan peligroso es acceder a una matriz fuera de los límites?

221

¿Qué tan peligroso es acceder a una matriz fuera de sus límites (en C)? A veces puede suceder que lea desde fuera de la matriz (ahora entiendo que luego accedo a la memoria utilizada por otras partes de mi programa o incluso más allá de eso) o estoy tratando de establecer un valor en un índice fuera de la matriz. El programa a veces se bloquea, pero a veces solo se ejecuta, solo da resultados inesperados.

Ahora, lo que me gustaría saber es, ¿qué tan peligroso es esto realmente? Si daña mi programa, no es tan malo. Si, por otro lado, rompe algo fuera de mi programa, porque de alguna manera logré acceder a una memoria totalmente no relacionada, entonces me imagino que es muy malo. Leí mucho 'todo puede pasar', 'la segmentación podría ser el problema menos grave' , 'tu disco duro podría ponerse rosado y los unicornios podrían estar cantando debajo de tu ventana', lo cual es agradable, pero ¿cuál es realmente el peligro?

Mis preguntas:

  1. ¿La lectura de valores desde fuera de la matriz puede dañar algo aparte de mi programa? Me imagino que solo mirar las cosas no cambia nada, o ¿cambiaría, por ejemplo, el atributo 'última vez abierto' de un archivo al que llegué?
  2. ¿Establecer valores fuera de la matriz puede dañar algo aparte de mi programa? De esta pregunta de desbordamiento de pila, deduzco que es posible acceder a cualquier ubicación de memoria, que no hay garantía de seguridad.
  3. Ahora ejecuto mis pequeños programas desde XCode. ¿Proporciona alguna protección adicional alrededor de mi programa donde no puede alcanzar fuera de su propia memoria? ¿Puede dañar XCode?
  4. ¿Alguna recomendación sobre cómo ejecutar mi código inherentemente con errores?

Yo uso OSX 10.7, Xcode 4.6.

ChrisD
fuente
En general, el sistema operativo se protegerá a sí mismo y a otros procesos de su malversación. Sin embargo, no es algo en lo que necesariamente quieras confiar.
Hot Licks
77
Además, nunca "alcanzará" un archivo en su disco duro cuando acceda y el índice de la matriz esté fuera de los límites (en su RAM).
DrummerB
1
Creo que estás preguntando acerca de C array, ¿verdad? así que eso no tiene nada que ver con ObjC y realmente no se relaciona con ningún IDE.
Bryan Chen
17
Este es mi ejemplo favorito de resultados extraños (se trata de la pila, pero lo encontré realmente esclarecedor ...).
phipsgabler
11
xkcd.com/371
Dan está

Respuestas:

125

En lo que respecta al estándar ISO C (la definición oficial del lenguaje), acceder a una matriz fuera de sus límites tiene un " comportamiento indefinido ". El significado literal de esto es:

comportamiento, al usar una construcción de programa no portable o errónea o de datos erróneos, para los cuales esta Norma Internacional no impone requisitos

Una nota no normativa se expande sobre esto:

El posible comportamiento indefinido varía desde ignorar la situación por completo con resultados impredecibles, hasta comportarse durante la traducción o la ejecución del programa de una manera documentada característica del entorno (con o sin la emisión de un mensaje de diagnóstico), hasta finalizar una traducción o ejecución (con la emisión de un mensaje de diagnóstico).

Entonces esa es la teoría. Cual es la realidad

En el "mejor" caso, accederá a un trozo de memoria que es propiedad de su programa actualmente en ejecución (lo que podría hacer que su programa se comporte mal), o que no sea propiedad de su programa actualmente en ejecución (lo que probablemente hará que su programa choque con algo así como una falla de segmentación). O puede intentar escribir en la memoria que posee su programa, pero eso está marcado como de solo lectura; Esto probablemente también hará que su programa se bloquee.

Eso supone que su programa se ejecuta bajo un sistema operativo que intenta proteger los procesos que se ejecutan simultáneamente entre sí. Si su código se está ejecutando en el "bare metal", diga si es parte de un kernel del sistema operativo o un sistema integrado, entonces no existe tal protección; su código de mal comportamiento es lo que se suponía que debía proporcionar esa protección. En ese caso, las posibilidades de daños son considerablemente mayores, incluyendo, en algunos casos, daños físicos al hardware (o cosas o personas cercanas).

Incluso en un entorno de SO protegido, las protecciones no siempre son del 100%. Hay errores del sistema operativo que permiten a los programas no privilegiados obtener acceso raíz (administrativo), por ejemplo. Incluso con privilegios de usuario normales, un programa que no funciona correctamente puede consumir recursos excesivos (CPU, memoria, disco), posiblemente averiando todo el sistema. Una gran cantidad de malware (virus, etc.) explota el desbordamiento del búfer para obtener acceso no autorizado al sistema.

(Un ejemplo histórico: he oído que en algunos sistemas antiguos con memoria central , acceder repetidamente a una única ubicación de memoria en un bucle cerrado podría literalmente derretir esa porción de memoria. Otras posibilidades incluyen destruir una pantalla CRT y mover la lectura / escribo en la cabeza de una unidad de disco con la frecuencia armónica del gabinete de la unidad, lo que hace que cruce una mesa y caiga al suelo).

Y siempre hay que preocuparse por Skynet .

La conclusión es esta: si pudieras escribir un programa para hacer algo mal deliberadamente , al menos teóricamente es posible que un programa defectuoso pueda hacer lo mismo accidentalmente .

En la práctica, es muy poco probable que su programa defectuoso que se ejecuta en un sistema MacOS X vaya a hacer algo más serio que el bloqueo. Pero no es posible evitar por completo que el código defectuoso haga cosas realmente malas.

Keith Thompson
fuente
1
gracias, realmente entiendo esto completamente. Pero inmediatamente provoca una pregunta de seguimiento: ¿qué puede hacer un programador principiante para proteger su computadora de sus propias creaciones posiblemente horribles? Después de haber probado un programa a fondo, puedo liberarlo en el mundo. Pero la primera ejecución de prueba está destinada a ser un programa incorrecto. ¿Cómo mantienen sus sistemas a salvo de ustedes mismos?
ChrisD
66
@ ChrisD: Tendemos a tener suerte. 8-)} En serio, la protección a nivel del sistema operativo es bastante buena en estos días. En el peor de los casos, si escribo una bomba tenedor accidental , podría tener que reiniciar para recuperarme. Pero probablemente no valga la pena preocuparse por el daño real al sistema, siempre que su programa no intente hacer algo al borde de ser peligroso. Si está realmente preocupado, ejecutar el programa en una máquina virtual podría no ser una mala idea.
Keith Thompson
1
Por otro lado, he visto muchas cosas raras que suceden en las computadoras que he usado (archivos dañados, errores irrecuperables del sistema, etc.), y no tengo idea de cuántas de ellas podrían haber sido causadas por algún programa de C el temido comportamiento indefinido. (Hasta el momento no hay demonios reales han volado por la nariz.)
Keith Thompson
1
gracias por enseñarme bombas de horquilla - He hecho cosas
similares
2
scientificamerican.com/article/… por lo que el fuego aún es posible con la electrónica moderna.
Mooing Duck
25

En general, los sistemas operativos de hoy (los más populares de todos modos) ejecutan todas las aplicaciones en regiones de memoria protegidas utilizando un administrador de memoria virtual. Resulta que no es terriblemente FÁCIL (por decir) simplemente leer o escribir en una ubicación que existe en un espacio REAL fuera de las regiones que se han asignado / asignado a su proceso.

Respuestas directas:

1) La lectura casi nunca dañará directamente otro proceso, sin embargo, puede dañar indirectamente un proceso si lees un valor CLAVE utilizado para cifrar, descifrar o validar un programa / proceso. Leer fuera de límites puede tener efectos algo adversos / inesperados en su código si está tomando decisiones basadas en los datos que está leyendo

2) La única forma en que realmente podría DAÑAR algo escribiendo en una ubicación accesible por una dirección de memoria es si esa dirección de memoria a la que está escribiendo es en realidad un registro de hardware (una ubicación que en realidad no es para el almacenamiento de datos sino para controlar alguna pieza de hardware) no es una ubicación RAM. De hecho, normalmente no dañará algo a menos que esté escribiendo una ubicación programable única que no sea regrabable (o algo por el estilo).

3) Generalmente, la ejecución desde el depurador ejecuta el código en modo de depuración. La ejecución en modo de depuración TENDE (pero no siempre) a detener su código más rápido cuando ha hecho algo considerado fuera de práctica o francamente ilegal.

4) Nunca use macros, use estructuras de datos que ya tengan una verificación de límites de índice de matriz incorporada, etc.

ADICIONAL Debería agregar que la información anterior es realmente solo para sistemas que usan un sistema operativo con ventanas de protección de memoria. Si escribe código para un sistema embebido o incluso un sistema que utiliza un sistema operativo (en tiempo real u otro) que no tiene ventanas de protección de memoria (o ventanas direccionadas virtuales), se debe tener mucha más precaución al leer y escribir en la memoria. También en estos casos, siempre deben emplearse prácticas de codificación SEGURAS y SEGURAS para evitar problemas de seguridad.

trompetas
fuente
44
Siempre deben emplearse prácticas de codificación seguras y seguras .
Nik Bougalis
3
Sugeriría NO usar try / catch para código con errores a menos que detecte excepciones muy específicas y sepa cómo recuperarse de ellas. Capturar (...) es lo peor que puede agregar a un código con errores.
Eugene
1
@NikBougalis - Estoy completamente de acuerdo, pero ES MÁS IMPORTANTE si el sistema operativo no incluye espacios de protección virtual / direcciones virtuales, o si falta un sistema operativo :-)
trumpetlicks
@Eugene - Nunca he dado cuenta de que para ser un problema para mí, pero estoy de acuerdo con usted, no he editado a cabo :-)
trumpetlicks
1) ¿te refieres a daño porque revelaría algo que debería haberse mantenido en secreto? 2) No estoy seguro de entender lo que quieres decir, pero supongo que solo estoy accediendo a la RAM al intentar acceder a ubicaciones fuera de los límites de la matriz.
ChrisD
9

No verificar los límites puede provocar efectos secundarios feos, incluidos agujeros de seguridad. Uno de los feos es la ejecución de código arbitrario . En el ejemplo clásico: si tiene una matriz de tamaño fijo y la usa strcpy()para colocar una cadena suministrada por el usuario, el usuario puede darle una cadena que desborde el búfer y sobrescriba otras ubicaciones de memoria, incluida la dirección de código donde la CPU debería regresar cuando su función acabados.

Lo que significa que su usuario puede enviarle una cadena que hará que su programa llame esencialmente exec("/bin/sh"), lo que lo convertirá en shell, ejecutando todo lo que quiera en su sistema, incluida la recolección de todos sus datos y convertir su máquina en un nodo botnet.

Vea Smashing The Stack por diversión y ganancias para obtener detalles sobre cómo se puede hacer esto.

che
fuente
Sé que no debería acceder a elementos de matriz más allá de los límites, gracias por reforzar ese punto. Pero la pregunta es, además de hacer todo tipo de daño a mi programa, ¿puedo alcanzar más allá de la memoria de mi programa sin querer? Y quiero decir en OSX.
ChrisD
@ChrisD: OS X es un sistema operativo moderno, por lo que le proporcionará protección total de la memoria. Por ejemplo, no debe limitarse a lo que su programa tiene permitido hacer. Esto no debe incluir jugar con otros procesos (a menos que se ejecute con privilegios de root).
che
Prefiero decir bajo privilegios de anillo 0, no privilegios de root.
Ruslan
Más interesante es que los compiladores hiper-moderna pueden decidir que si intenta código para leer foo[0]a través foo[len-1]después de haber utilizado previamente un cheque de lenen contra de la longitud de la matriz o bien ejecutar o saltar una pieza de código, el compilador debe sentirse libre para ejecutar ese otro código incondicionalmente, incluso si la aplicación posee el almacenamiento más allá de la matriz y los efectos de la lectura hubiera sido benigno, pero el efecto de invocar el otro código no lo sería.
supercat
8

Usted escribe:

Leí mucho 'todo puede pasar', 'la segmentación podría ser el problema menos grave', 'tu disco duro podría ponerse rosado y los unicornios podrían estar cantando debajo de tu ventana', lo cual es agradable, pero ¿cuál es realmente el peligro?

Digámoslo así: cargue un arma. Apúntelo fuera de la ventana sin ningún objetivo particular y dispare. Cual es el peligro

El problema es que no lo sabes. Si su código sobrescribe algo que bloquea su programa, está bien porque lo detendrá en un estado definido. Sin embargo, si no se bloquea, los problemas comienzan a surgir. ¿Qué recursos están bajo el control de su programa y qué podría hacerles? ¿Qué recursos podrían estar bajo el control de su programa y qué podría hacerles? Conozco al menos un problema importante causado por tal desbordamiento. El problema estaba en una función de estadísticas aparentemente sin sentido que estropeó alguna tabla de conversión no relacionada para una base de datos de producción. El resultado fue una limpieza muy costosa después. En realidad, hubiera sido mucho más barato y fácil de manejar si este problema hubiera formateado los discos duros ... con otras palabras: los unicornios rosados ​​podrían ser su menor problema.

La idea de que su sistema operativo lo protegerá es optimista. Si es posible, trate de evitar escribir fuera de los límites.

Udo Klein
fuente
ok, esto era exactamente de lo que tenía miedo. Trataré de evitar escribir fuera de los límites, pero, viendo lo que he estado haciendo en los últimos meses, seguramente lo seguiré haciendo mucho. ¿Cómo se volvieron tan buenos en la programación sin una forma segura de practicar?
ChrisD
3
¿Quién dijo que algo estaba a salvo?)
Udo Klein
7

No ejecutar su programa como usuario root o cualquier otro usuario privilegiado no dañará ninguno de su sistema, por lo que, en general, puede ser una buena idea.

Al escribir datos en alguna ubicación de memoria aleatoria, no "dañará" directamente ningún otro programa que se ejecute en su computadora, ya que cada proceso se ejecuta en su propio espacio de memoria.

Si intenta acceder a cualquier memoria no asignada a su proceso, el sistema operativo detendrá la ejecución de su programa con una falla de segmentación.

Entonces, directamente (sin ejecutarse como root y acceder directamente a archivos como / dev / mem) no hay peligro de que su programa interfiera con cualquier otro programa que se ejecute en su sistema operativo.

Sin embargo, y probablemente esto es de lo que ha oído hablar en términos de peligro, al escribir a ciegas datos aleatorios en ubicaciones de memoria aleatorias por accidente, puede dañar cualquier cosa que pueda dañar.

Por ejemplo, su programa puede querer eliminar un archivo específico dado por un nombre de archivo almacenado en algún lugar de su programa. Si por accidente simplemente sobrescribe la ubicación donde se almacena el nombre del archivo, puede eliminar un archivo muy diferente.

mikyra
fuente
1
Sin embargo, si se está ejecutando como root (o algún otro usuario privilegiado), tenga cuidado. Los desbordamientos de búfer y matriz son un exploit de malware común.
John Bode
en realidad, la cuenta que uso para toda mi informática diaria no es una cuenta de administrador (uso la terminología OSX ya que ese es mi sistema). ¿Quiere decirme que no puedo dañar algo intentando establecer CUALQUIER ubicación de memoria? ¡Eso es realmente una gran noticia!
ChrisD
Como ya se mencionó anteriormente, el peor daño que puede hacer por accidente es el peor daño que puede hacer como usuario. Si desea estar 100% seguro de no destruir ninguno de sus datos, probablemente desee agregar una cuenta diferente a su computadora y experimentar con eso.
mikyra
1
@mikyra: Eso es cierto solo si los mecanismos de protección del sistema son 100% efectivos. La existencia de malware sugiere que no siempre se puede confiar en eso. (No quiero sugerir que eso es necesariamente vale la pena preocuparse, es posible, pero poco probable, de que un programa podría querer explotar los mismos agujeros de seguridad explotados por el malware.)
Keith Thompson
1
La lista aquí incluye: Código de ejecución de fuentes no confiables. Simplemente haga clic en el botón Aceptar en cualquier ventana emergente del firewall sin siquiera leer de qué se trata o apagarlo por completo si no se puede establecer la conexión de red deseada. Parchear binarios con el último truco de fuentes dudosas. No es culpa de la bóveda si el propietario invitará voluntariamente a cualquier ladrón con ambos brazos y puertas fortificadas extra fuertes abiertas de par en par.
mikyra
4

NSArrays en Objective-C se les asigna un bloque específico de memoria. Exceder los límites de la matriz significa que accedería a la memoria que no está asignada a la matriz. Esto significa:

  1. Esta memoria puede tener cualquier valor. No hay forma de saber si los datos son válidos en función de su tipo de datos.
  2. Esta memoria puede contener información confidencial, como claves privadas u otras credenciales de usuario.
  3. La dirección de memoria puede ser inválida o protegida.
  4. La memoria puede tener un valor cambiante porque otro programa o subproceso está accediendo a ella.
  5. Otras cosas usan el espacio de direcciones de memoria, como los puertos asignados a memoria.
  6. Escribir datos en una dirección de memoria desconocida puede bloquear su programa, sobrescribir el espacio de memoria del sistema operativo y, en general, hacer que el sol implosione.

Desde el aspecto de su programa, siempre quiere saber cuándo su código excede los límites de una matriz. Esto puede provocar que se devuelvan valores desconocidos, haciendo que su aplicación se bloquee o proporcione datos no válidos.

Richard Brown
fuente
NSArraystener excepciones fuera de límites. Y estas preguntas parecen ser sobre la matriz C.
DrummerB
De hecho, me refería a las matrices C. Sé que hay NSArray, pero por ahora la mayoría de mis ejercicios están en C
ChrisD
4

Es posible que desee intentar usar la memcheckherramienta en Valgrind cuando pruebe su código: no detectará violaciones de límites de matriz individuales dentro de un marco de pila, pero debería detectar muchos otros tipos de problemas de memoria, incluidos los que causarían sutiles, más amplios problemas fuera del alcance de una sola función.

Del manual:

Memcheck es un detector de errores de memoria. Puede detectar los siguientes problemas que son comunes en los programas C y C ++.

  • No debe acceder a la memoria, p. Ej., Sobrepasar y superar los bloques de almacenamiento dinámico, sobrepasar la parte superior de la pila y acceder a la memoria después de que se haya liberado.
  • Usar valores indefinidos, es decir, valores que no se han inicializado o que se han derivado de otros valores indefinidos.
  • Liberación incorrecta de memoria de almacenamiento dinámico, como bloques de almacenamiento dinámico de liberación doble o uso no coincidente de malloc / new / new [] versus free / delete / delete []
  • Superposición de punteros src y dst en memcpy y funciones relacionadas.
  • Pérdidas de memoria.

ETA: Sin embargo, como dice la respuesta de Kaz, no es una panacea, y no siempre da el resultado más útil, especialmente cuando se utilizan patrones de acceso interesantes .

Aesin
fuente
¿Sospecharía que el Analizador de XCode encontraría la mayor parte de eso? y mi pregunta no es tanto cómo encontrar estos errores, pero si ejecutar un programa que todavía tiene estos errores es peligroso para la memoria no asignada a mi programa. Tendré que ejecutar el programa para ver los errores que ocurren
ChrisD
3

Si alguna vez realiza la programación a nivel de sistemas o la programación de sistemas integrados, pueden ocurrir cosas muy malas si escribe en ubicaciones de memoria aleatorias. Los sistemas más antiguos y muchos microcontroladores usan IO mapeada en memoria, por lo que escribir en una ubicación de memoria que se mapea en un registro periférico puede causar estragos, especialmente si se hace de forma asincrónica.

Un ejemplo es la programación de memoria flash. El modo de programación en los chips de memoria se habilita escribiendo una secuencia específica de valores en ubicaciones específicas dentro del rango de direcciones del chip. Si otro proceso se escribiera en cualquier otra ubicación en el chip mientras eso sucedía, causaría que el ciclo de programación fallara.

En algunos casos, el hardware ajustará las direcciones (se ignoran los bits / bytes más significativos de la dirección), por lo que escribir en una dirección más allá del final del espacio de direcciones físicas dará como resultado que los datos se escriban justo en el medio de las cosas.

Y finalmente, las CPU más antiguas como el MC68000 pueden bloquearse hasta el punto de que solo un reinicio de hardware puede hacer que vuelvan a funcionar. No he trabajado en ellos durante un par de décadas, pero creo que es cuando se encontró con un error de bus (memoria inexistente) al tratar de manejar una excepción, simplemente se detendría hasta que se confirmara el restablecimiento del hardware.

Mi mayor recomendación es un enchufe descarado para un producto, pero no tengo ningún interés personal en él y no estoy afiliado a ellos de ninguna manera, pero basado en un par de décadas de programación en C y sistemas integrados donde la confiabilidad era crítica, la PC de Gimpel Lint no solo detectará ese tipo de errores, sino que también lo convertirá en un mejor programador de C / C ++ al insistir constantemente sobre los malos hábitos.

También recomiendo leer el estándar de codificación MISRA C, si puede enganchar una copia de alguien. No he visto ninguno reciente, pero en los viejos tiempos daban una buena explicación de por qué deberías / no deberías hacer las cosas que cubren.

No sé sobre ti, pero sobre la segunda o tercera vez que recibo un coredump o un bloqueo de cualquier aplicación, mi opinión sobre cualquier compañía que la produzca se reduce a la mitad. La 4ta o 5ta vez y cualquiera que sea el paquete se convierte en estantería y conduzco una estaca de madera a través del centro del paquete / disco en el que vino solo para asegurarme de que nunca vuelva a perseguirme.

Dan Haynes
fuente
Dependiendo del sistema, las lecturas fuera de rango también pueden desencadenar un comportamiento impredecible, o pueden ser benignas, aunque el comportamiento benigno del hardware en cargas fuera de rango no implica un comportamiento benigno del compilador.
supercat
2

Estoy trabajando con un compilador para un chip DSP que genera deliberadamente código que accede a uno más allá del final de una matriz de código C que no lo hace.

Esto se debe a que los bucles están estructurados de modo que el final de una iteración capta previamente algunos datos para la siguiente iteración. Por lo tanto, el datum captado previamente al final de la última iteración nunca se usa realmente.

Escribir código C como ese invoca un comportamiento indefinido, pero eso es solo una formalidad de un documento estándar que se ocupa de la máxima portabilidad.

Más a menudo que no, un programa que accede fuera de los límites no está inteligentemente optimizado. Es simplemente con errores. El código obtiene algún valor de basura y, a diferencia de los bucles optimizados del compilador mencionado anteriormente, el código luego usa el valor en cálculos posteriores, corrompiéndolos.

Vale la pena detectar errores como ese, por lo que vale la pena hacer que el comportamiento sea indefinido, incluso por esa sola razón: para que el tiempo de ejecución pueda producir un mensaje de diagnóstico como "desbordamiento de matriz en la línea 42 de main.c".

En los sistemas con memoria virtual, se podría asignar una matriz de manera que la dirección que sigue esté en un área no asignada de memoria virtual. El acceso luego bombardeará el programa.

Como comentario adicional, tenga en cuenta que en C se nos permite crear un puntero que está uno más allá del final de una matriz. Y este puntero tiene que comparar más que cualquier puntero con el interior de una matriz. Esto significa que una implementación en C no puede colocar una matriz justo al final de la memoria, donde la dirección uno más se ajustaría y se vería más pequeña que otras direcciones en la matriz.

Sin embargo, el acceso a valores no inicializados o fuera de los límites a veces es una técnica de optimización válida, incluso si no es máximamente portátil. Esta es, por ejemplo, la razón por la cual la herramienta Valgrind no informa accesos a datos no inicializados cuando esos accesos suceden, sino solo cuando el valor se usa más tarde de alguna manera que podría afectar el resultado del programa. Obtiene un diagnóstico como "rama condicional en xxx: nnn depende del valor no inicializado" y a veces puede ser difícil rastrear dónde se origina. Si todos estos accesos quedaran atrapados de inmediato, habría muchos falsos positivos derivados del código optimizado del compilador, así como del código correctamente optimizado a mano.

Hablando de eso, estaba trabajando con un códec de un proveedor que emitía estos errores cuando se transfirió a Linux y se ejecutó bajo Valgrind. Pero el vendedor me convenció de que solo varios bitsdel valor que se usa en realidad proviene de la memoria no inicializada, y esos bits fueron cuidadosamente evitados por la lógica. Solo se estaban usando los bits buenos del valor y Valgrind no tiene la capacidad de rastrear el bit individual. El material no inicializado proviene de leer una palabra más allá del final de un flujo de bits de datos codificados, pero el código sabe cuántos bits hay en el flujo y no utilizará más bits de los que realmente hay. Dado que el acceso más allá del final de la matriz de flujo de bits no causa ningún daño en la arquitectura DSP (no hay memoria virtual después de la matriz, no hay puertos mapeados en memoria y la dirección no se ajusta) es una técnica de optimización válida.

"Comportamiento indefinido" en realidad no significa mucho, porque de acuerdo con ISO C, simplemente incluir un encabezado que no está definido en el estándar C, o llamar a una función que no está definida en el propio programa o el estándar C, son ejemplos de indefinido comportamiento. El comportamiento indefinido no significa "no definido por nadie en el planeta" simplemente "no definido por el estándar ISO C". Pero, por supuesto, el comportamiento a veces sin definir realmente es absolutamente no definido por cualquiera.

Kaz
fuente
Además, siempre que exista al menos un programa que una implementación en particular procese correctamente a pesar de que grava nominalmente todos los límites de implementación establecidos en la Norma, esa implementación podría comportarse de manera arbitraria cuando se alimenta a cualquier otro programa que esté libre de violaciones de restricciones y aún sea " obediente". En consecuencia, el 99.999% de los programas en C (cualquier cosa que no sea el "programa único" de una plataforma) se basan en comportamientos donde el Estándar no impone requisitos.
supercat
1

Además de su propio programa, no creo que rompa nada, en el peor de los casos intentará leer o escribir desde una dirección de memoria que corresponda a una página que el núcleo no asignó a sus procesos, generando la excepción adecuada y ser asesinado (quiero decir, su proceso).

jbgs
fuente
3
..¿Qué? ¿Qué hay de sobrescribir la memoria en su propio proceso utilizado para almacenar alguna variable utilizada más tarde ... que ahora ha cambiado misteriosamente su valor! Esos bichos son muy divertidos de rastrear, te lo aseguro. Un segfault sería el mejor resultado. -1
Ed S.
2
Quiero decir que no "interrumpirá" otros procesos, además de su propio programa;)
jbgs
De hecho, no me importa si rompo mi propio programa. Solo estoy aprendiendo, el programa obviamente está mal de todos modos si accedo a algo fuera de mi matriz. Me estoy preocupando cada vez más por los riesgos de romper algo más al depurar mis creaciones
ChrisD
La cuestión es: ¿puedo estar seguro de que si intento acceder a la memoria que no se me ha asignado, se cerrará mi proceso? (estar en OSX)
ChrisD
3
Hace años, solía ser un torpe programador en C. Accedí a matrices fuera de sus límites cientos de veces. Además de que el sistema operativo eliminó mi proceso, nunca sucedió nada.
jbgs