2012-09-13 17 views
5

¿Por qué no está dando error cuando compilo?¿Por qué no obtengo un error de segmentación cuando escribo más allá del final de una matriz?

#include <iostream> 
using namespace std; 

int main() 
{ 
    int *a = new int[2]; 
    // int a[2]; // even this is not giving error 
    a[0] = 0; 
    a[1] = 1; 
    a[2] = 2; 
    a[3] = 3; 
    a[100] = 4; 
    int b; 

    return 0; 
} 

alguien puede explicar por qué sucede esto. Gracias de antemano.)

+4

Desafortunadamente, el comportamiento definido ** a veces ** es un subconjunto de comportamiento indefinido :( – Mahesh

+0

@Mahesh :)) no. –

+1

@LuchianGrigore ** A veces ** – Mahesh

Respuesta

2

Supongo que proviene de Java o de un lenguaje similar a Java donde una vez que sale del límite de una matriz, obtiene la excepción "array index out of bounds".

Bueno, C espera más de usted; ahorra el espacio que pides, pero no verifica si estás saliendo del límite de ese espacio guardado. Una vez que haces eso como se mencionó anteriormente, el programa tiene ese temido comportamiento indefinido.

Y recuerda que para el futuro si tiene un error en su programa y parece que no puede encontrarlo, y al momento sobre el código/depurarlo, todo parece bien, hay una buena probabilidad de que' re "fuera de límites" y acceder a un lugar no asignado.

9

Debido a un comportamiento indefinido == puede pasar cualquier cosa. Tienes la mala suerte de que no se cuelgue, este tipo de comportamiento puede ocultar errores.

En cuanto a a se define dos veces, eso es un error en el compilador.

+0

Lo siento. "a" no fue declarado dos veces. Solo quería decir que ambas declaraciones se comportan de manera similar. – singingsingh

+0

@singingsingh ok :) luego haga caso omiso del segundo párrafo. –

8

Declarar dos variables llamadas a ciertamente es un error; si tu compilador acepta eso, entonces está roto. Supongo que quiere decir que aún no obtiene un error si reemplaza una declaración con la otra.

El acceso al array no está controlado por rango. En tiempo de compilación, el tamaño de una matriz a menudo no se conoce, y el idioma no requiere una comprobación, incluso cuando lo es. En tiempo de ejecución, un cheque podría degradar el rendimiento, lo que iría en contra de la filosofía C++ de no pagar por algo que no necesita. Entonces, el acceso más allá del final de una matriz proporciona un comportamiento indefinido, y depende del programador asegurarse de que no suceda.

A veces, un acceso no válido causará un error de segmentación, pero esto no está garantizado. Por lo general, la protección de memoria solo se aplica a páginas completas de memoria, con un tamaño de página típico de algunos kilobytes. Cualquier acceso dentro de una página de memoria válida no será capturado. Hay muchas posibilidades de que la memoria a la que accedes contenga alguna otra variable de programa, o parte de la pila de llamadas, por lo que escribir allí podría afectar el comportamiento del programa de cualquier forma que puedas imaginar.

Si quiere estar seguro, puede usar std::vector, y solo acceder a sus elementos usando su función at(). Esto verificará el índice y arrojará una excepción si está fuera de rango. También administrará la asignación de memoria para usted, corrigiendo la pérdida de memoria en su ejemplo.

+0

Lo siento. "a" no fue declarado dos veces. Solo quería decir que ambas declaraciones se comportan de manera similar. – singingsingh

0

compiladores con buen análisis de código sin duda advertirían sobre el código que hace referencia más allá de su asignación de matriz. olvidando la declaración de múltiples, si la ejecutó, puede o no tener fallas (comportamiento indefinido como otros han dicho). si, por ejemplo, tiene una página de 4KB de capacidad (en el espacio de direcciones del procesador), si no escribe fuera de esa página, no obtendrá un error del procesador. al eliminar la matriz, si lo había hecho, y dependiendo de la implementación del montón, el montón podría detectar que está dañado.

Cuestiones relacionadas