¿Por qué const int main = 195 resulta en un programa de trabajo pero sin el const termina en un fallo de segmentación?


Considere seguir el programa C (vea la demostración en vivo aquí).

const int main = 195;

Sé que en el mundo real ningún programador escribe código como este, porque no tiene ningún propósito útil y no tiene ningún sentido. Pero cuando elimino la palabra clave const de arriba del programa, inmediatamente resulta en un error de segmentación . ¿Por qué? Estoy ansioso por saber la razón detrás de esto.

GCC 4.8.2 da la siguiente advertencia al compilarlo.

Advertencia: 'principal' suele ser un función [- Wmain]

const int main = 195;
          ^

¿Por qué la presencia y ausencia de la palabra clave const hacen una diferencia aquí en el comportamiento del programa?

Author: fuz, 2015-10-23

2 answers

Observe cómo el valor 195 corresponde a la instrucción ret (return from function) en 8086 compatibles. Esta definición de main se comporta como si lo definiera como int main() {} cuando se ejecuta.

En algunas plataformas, const los datos se cargan en una región de memoria ejecutable pero no ejecutable, mientras que los datos mutables (es decir, datos no calificados const) se cargan en una región de memoria ejecutable pero no ejecutable. Por esta razón, el programa "funciona" cuando se declara main como const pero no cuando omites el calificador const.

Tradicionalmente, los binarios contenían tres segmentos:

  • El segmento text es (si está soportado por la arquitectura) protegido contra escritura y ejecutable, y contiene código ejecutable, variables de estática duración de almacenamiento calificada const, y literales de cadena
  • El segmento data es escribible y no se puede ejecutar. Contiene variables no calificadas const con estática duración de almacenamiento y (en runtime) objects with allocated storage duration
  • El segmento bss es similar al segmento data pero se inicializa a todos los ceros. Contiene variables de estática duración de almacenamiento no calificada const que han sido declaradas sin inicializador
  • El segmento stack no está presente en el binario y contiene variables con automático duración de almacenamiento

Eliminar el calificador const de la variable main lo hace para ser movido del segmento text al segmento data, que no es ejecutable, causando la violación de segmentación que observa.

Las plataformas modernas a menudo tienen segmentos adicionales (por ejemplo, un segmento rodata para datos que no se pueden escribir ni ejecutar), así que no tome esto como una descripción precisa de su plataforma sin consultar la documentación específica de la plataforma.

Por favor, comprenda que no hacer main una función suele ser incorrecto, aunque técnicamente una plataforma podría permitir que main se declare como variable, cf. ISO 9899: 2011 §5.1.2.2.1 ¶1, énfasis mío:

1 La función llamada al inicio del programa se llama main. La implementación no declara ningún prototipo para esta función. Se definirá con un tipo de retorno de int y sin parámetros (...) o con dos parámetros (...) o equivalente; o de alguna otra manera definida por la implementación.

 59
Author: fuz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-24 15:20:55

En C, main en el ámbito global es casi siempre una función.

Usar main como variable en el ámbito global hace que el comportamiento del programa sea indefinido.

(Simplemente podría ser que cuando escribes const el compilador optimiza la variable a una constante y así tu comportamiento del programa es diferente. Pero el comportamiento del programa es todavía indefinido).

 11
Author: Bathsheba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-23 15:14:49