2017-09-02 5 views
0

GCC/G ++ de MingW donne des erreurs de relocalisation lors de la création d'applications avec de grandes données globales ou statiques.MingW Windows GCC ne peut pas compiler un programme c avec des données globales de 2 Go

Understanding the x64 code models

Les références à la fois le code et les données sur 64 bits sont effectués avec instruction de rapport (RIP-parent dans le langage x64) modes d'adressage. Le décalage de RIP dans ces instructions est limité à 32 bits.

Le petit modèle de code promet au compilateur que les décalages relatifs 32 bits devraient être suffisants pour toutes les références de code et de données dans l'objet compilé. D'autre part, le modèle à grand code lui dit de ne pas faire d'hypothèses et d'utiliser des modes d'adressage absolus de 64 bits pour les références de code et . Pour rendre les choses plus intéressantes, il y a aussi une route intermédiaire , appelée le modèle de code moyen.

Pour le programme d'exemple ci-dessous, malgré l'ajout d'options mcmodel = moyenne ou -mcmodel = grand le code ne peut pas compiler

#define SIZE 16384 
float a[SIZE][SIZE], b[SIZE][SIZE]; 

int main(){ 
return 0; 
} 

gcc -mcmodel=medium example.c fails to compile on MingW/Cygwin Windows, Intel windows /MSVC 
+0

Veuillez publier la sortie du compilateur. –

+0

1. Intel de Windows/MSVC2015 LINK: erreur fatale LNK1248: taille de l'image (8000A000) dépasse la taille maximale admissible (80000000) 2. Mingw, Cygwin "relocalisation tronquée pour s'adapter: R_X86_64_PC32 contre" Windows => 3 Compile sur GCC 4.8 Linux (sous-système Linux (Ubuntu 14.04) de Windows nouvelle mise à jour d'anniversaire) et d'autres distributions GCC linux sur Ubuntu 4. Il semble que l'option de compilation mcmodel n'est pas autorisée sur aucune fenêtre gcc ciblée – Dhiraj

+0

Je pensais que nous avions tout quitté ce modèle de mémoire des ordures derrière avec le mode réel x86. Je frémis encore à l'idée des mots minuscules, petits, moyens, compacts, grands et immenses à proximité :-) – paxdiablo

Répondre

2

Vous êtes limité à 32 bits pour un décalage, mais est signé décalage. Donc en pratique, vous êtes limité à 2GiB. Vous avez demandé pourquoi ce n'est pas possible, mais votre tableau seul est de 2GiB et il y a des choses dans le segment de données autre que votre tableau. C est un langage de haut niveau. Vous obtenez la facilité de pouvoir définir une fonction principale et vous obtenez toutes ces autres choses gratuitement - une entrée et sortie standard, etc. L'exécution C implémente cela pour vous et tout cela consomme de l'espace et de la place dans la pile. votre segment de données. Par exemple, si je compile ceci sur x86_64-pc-linux-gnu ma taille .bss est 0x80000020 - 32 octets supplémentaires. (J'ai effacé les informations PE de mon cerveau, donc je ne me souviens pas comment elles sont disposées.)

Je ne me souviens pas beaucoup des différents modèles de machines, mais il est probablement utile de noter que l'instruction x86_64 set ne contient même pas d'instructions (dont je suis conscient, bien que je ne sois pas un expert en assemblage x86) pour accéder à une adresse relative au registre au-delà d'une valeur 32 bits signée. Par exemple, lorsque vous voulez entasser que de choses sur la pile, gcc doit faire des choses étranges comme cette allocation de pointeur de pile:

movabsq $-10000000016, %r11 
    addq %r11, %rsp 

Vous ne pouvez pas addq $-10000000016, %rsp parce qu'il est plus d'un 32 bits signé offset. La même chose s'applique à l'adressage RIP:

movq $10000000016(%rip), %rax # No such addressing mode 
+1

Mais ce tableau n'est pas sur la pile, c'est une variable globale. – ssbssa

+0

@ssbassa: Merci, j'ai mis à jour ma réponse. Je ne me souviens pas vraiment de ces machines et peut-être que quelqu'un aura une meilleure réponse. Mais le principe de la salle d'exécution C nécessitant de la place s'applique également au segment de données de l'image. –