2012-02-09 12 views
8

De acuerdo con this reddit comment thread, no está definido si se intenta leer la memoria antes de que se haya escrito. Me refiero a la memoria de pila normal que ha sido exitosamente malloc ed.leer antes de escribir no está definido con memoria mallada?

... cuenta que esto no es estrictamente válida C: se permite que el sistema de compilador/tiempo de ejecución para inicializar la memoria sin inicializar con los llamados representaciones trampa, lo que causa un comportamiento indefinido en el acceso.

Encuentro esto difícil de creer. ¿Hay una cita estándar?

Por supuesto, entiendo que no hay garantía de que la memoria se haya reducido a cero. Los valores en esta memoria no inicializada son esencialmente pseudoaleatorios o arbitrarios. Pero realmente no puedo creer que el estándar se refiera a esto como comportamiento indefinido (en el sentido de que podría segfault, o eliminar todos sus archivos, o lo que sea). El resto del hilo de reddit no arrojó más luz sobre este tema.

+0

Erm, ¿qué crees que significa comportamiento indefinido? (Sí, usar la memoria asignada antes de que se haya inicializado produce un comportamiento indefinido) –

+1

@Brian Supongo que está preguntando si todo el comportamiento (es decir, esta segfault) no está definido, o solo el valor que resultaría de la lectura. – Owen

+0

@Owen, es cierto, he actualizado la pregunta en consecuencia. –

Respuesta

10

Si se accede a través de un char*, esto está definido. Pero de lo contrario, este es un comportamiento indefinido.

(C99, 7.20.3.3) "La función malloc asigna espacio para un objeto cuyo tamaño se especifica por tamaño y cuyo valor es indeterminado."

en el valor indeterminado:

(C99, 3.17.2p1) "valor indeterminado: o bien un valor no especificada o una representación trampa"

en representación trampa lectura a través de un no -carácter tipo siendo comportamiento indefinido:

(C99, 6.2.6.1p5) "Ciertas representaciones de objetos no necesitan representar un valor del tipo de objeto. Si el valor almacenado de un objeto tiene tal representación y es leído por una expresión lvalue que no tiene un tipo de carácter, el comportamiento no está definido. ] Tal representación se llama una representación de trampa ".

+1

Agregue una cotización estándar que indique que el acceso a una representación de trampa da como resultado un comportamiento indefinido, y tendrá la cadena completa. (Pero, a partir de este comentario, todavía te estás perdiendo ese.) –

+0

@BrooksMoses hecho – ouah

+0

@BrooksMoses, esa es la gran pregunta. ¿Qué significa "representación de trampas"? –

1

ISO/IEC 9899:1999, 7.20.3.3 La función malloc:

La función malloc asigna espacio para un objeto cuyo tamaño está especificado por tamaño y cuyo valor es indeterminado.

6.2.6.1 Representación de tipos, § 5:

Ciertas representaciones de objetos no tienen que representan un valor del tipo de objeto. Si el valor almacenado de un objeto tiene tal representación y es leído por una expresión lvalue que no tiene el tipo de carácter , el comportamiento no está definido.

Y la nota 41 lo hace aún más explícita (por lo menos para las variables automáticas):

Por lo tanto, una variable automática se puede inicializar a una representación trampa sin causar un comportamiento indefinido, pero el valor de la la variable no se puede usar hasta que se almacene un valor apropiado en ella.

+0

No tengo ningún problema con 'valor indeterminado'. Eso está claro en la respuesta. La pregunta es si el comportamiento es totalmente indefinido (segfaults, etc.). –

+1

¿Está bien a través de 'char *'? ¿Puedes dar un ejemplo de tal objeto? Estoy tratando de recordar cómo se representan 'double's, quizás no todas las configuraciones de bits se asignan a un' doble' válido. ¿Es este el tipo de cosa al que se hace referencia aquí? –

+1

Existen varios tipos de valores 'NaN' (" no un número ") que forman parte de la representación estándar' doble', pero que aún son "válidos". –

2

Es racionalmente indefinido. De lo contrario, el comportamiento necesario de un programa C que se ejecute en algo como Valgrind, que diagnostica lecturas de memoria no inicializada y arroja errores apropiados cuando ocurren, sería ilegal según el estándar.

Leyendo el estándar, la pregunta clave es si los valores de memoria malloc'ed son "valores no especificados" (que debe ser algún valor legible), o "valores indeterminados" (que pueden contener representaciones trampa; cf definición 3.17. 2.)

Según 7.20.3.3, citado en las otras respuestas, malloc devuelve un bloque de memoria que contiene valores indeterminados y, por lo tanto, puede contener representaciones de trampas. La discusión relevante de las representaciones de trampas es 6.2.6.1, parte 5:

Ciertas representaciones de objetos no necesitan representar un valor del tipo de objeto. Si el valor almacenado de un objeto tiene tal representación y es leído por una expresión lvalue que no tiene un tipo de carácter, el comportamiento no está definido. ... Tal representación se denomina representación de trampa .

Así que, ahí lo tienes. Básicamente, se permite que la implementación C detecte (es decir, "intercepte") referencias a valores indeterminados y trate ese error como lo desee, incluso de formas no definidas.

+0

¿Por qué es necesario que herramientas como Valgrind se comporten como implementaciones de C totalmente conformes? Yo sugeriría que en muchos casos sería más útil para ellos ser configurables para atrapar en una variedad de cosas que se consideran totalmente definidas por el estándar pero que el programador sabe que nunca sucederán sino por accidente. – supercat