Un Débordement de pile dans le programme Fortran
J'ai un problème avec mon simple programme Fortran. Je travaille en Fortran 77, à l'aide de Compaq Visual Fortran. La structure du programme doit être sous la forme d'une main et d'une sous-routine, parce qu'il fait partie d'un grand programme lié à la méthode des éléments finis.
Mon problème est que je voudrais définir les valeurs 10000 & 10000 pour NHELE
et NVELE
respectivement, mais quand je lance le code, le programme s'arrête et donne l'erreur suivante:
forrt1: server <170>: program Exception - stack overflow
J'ai essayé de réduire de manière itérative les valeurs requises, jusqu'à ce que j'ai atteint 507 & 507. À ce stade, le code s'exécute sans erreur.
Cependant, l'augmentation des valeurs à 508 & 508 provoque la même erreur à nouveau.
Je pense que le problème est lié à la sous-routine NIGTEE
, parce que quand j'ai réorganiser le programme sans elle, tout fonctionne bien.
J'ai tenté d'augmenter la taille de la pile pour un maximum en utilisant le menu project>>settings>>link>>output>>reserve & commit
mais ceci n'est pas de faire une différence.
Comment puis-je résoudre ce problème?
Voici mon programme:
PARAMETER(NHELE=508,NVELE=508)
PARAMETER(NHNODE=NHELE+1,NVNODE=NVELE+1)
PARAMETER(NTOTALELE=NHELE*NVELE)
DIMENSION MELE(NTOTALELE,4)
CALL NIGTEE(NHELE,NVELE,NHNODE,NVNODE,NTOTALELE,MELE)
OPEN(UNIT=7,FILE='MeshNO For Rectangular.TXT',STATUS='UNKNOWN')
WRITE(7,500) ((MELE(I,J),J=1,4),I=1,NTOTALELE)
500 FORMAT(4I20)
STOP
END
SUBROUTINE NIGTEE(NHELE,NVELE,NHNODE,NVNODE,NTOTALELE,MELE)
DIMENSION NM(NVNODE,NHNODE),NODE(4)
DIMENSION MELE(NTOTALELE,4)
KK=0
DO 20 I=1,NVNODE
DO 20 J=1,NHNODE
KK=KK+1
NM(I,J)=KK
20 CONTINUE
KK=0
DO 30 I=1,NVELE
DO 30 J=1,NHELE
NODE(1)=NM(I,J)
NODE(2)=NM(I,J+1)
NODE(3)=NM(I+1,J+1)
NODE(4)=NM(I+1,J)
KK=KK+1
DO 50 II=1,4
50 MELE(KK,II)=NODE(II)
30 CONTINUE
RETURN
END
Grâce.
OriginalL'auteur ghazooo | 2009-10-30
Vous devez vous connecter pour publier un commentaire.
Mise à jour:
Voici votre problème actuel. Votre
NM
tableau est déclaré comme un tableau à deux dimensions deNHNODE
cellules parNVNODE
lignes. Si c'est 10 000 par 10 000, alors vous aurez besoin de plus de 381 mo de mémoire pour allouer ce tableau à lui seul, à l'exclusion de toute autre mémoire utilisée par votre programme. (Par contre, si le tableau est de 500 par 500, vous avez seulement besoin d'environ 1 méga-octet de mémoire pour le même tableau.)Le problème c'est que les vieux Fortran permettrait d'affecter tous les tableaux directement dans le segment de code ou sur la pile. Le concept d'un OS "tas" (à des fins générales de la mémoire pour les objets volumineux) a été inventé en 1977, mais Fortran 77 n'a toujours pas ont tout construit pour l'utiliser. Donc à chaque fois que votre sous-routine est appelée, elle a qu'à pousser le pointeur de pile pour faire de la place pour 381 mo d'espace sur la pile. Ce n'est presque certainement plus grande que la quantité d'espace de votre système d'exploitation permettant le segment de pile, et vous êtes débordement de la pile de la mémoire (et donc l'obtention d'un un débordement de pile).
La solution est d'allouer de la mémoire à partir d'un endroit différent. Je sais que dans le vieux Fortran il est possible d'utiliser
COMMON
blocs statiquement allouer de la mémoire directement à partir de votre segment de code. Vous ne pouvez toujours pas allouer dynamiquement de plus, si votre sous-routine peut pas être réentrant, mais si votre sous-routine seulement est appelé à la fois à un (ce qui semble être) ce peut être la meilleure solution.Serait une meilleure solution pour passer en Fortran 90 ou plus récent et utiliser le
ALLOCATE
mot-clé pour allouer dynamiquement des tableaux sur le tas au lieu de la pile. Ensuite, vous pouvez affecter un morceau comme votre OS peut vous donner, mais vous n'aurez pas à vous soucier de débordement de la pile, car la mémoire est à venir à partir d'un autre endroit.Vous pouvez peut-être résoudre ce problème en modifiant le compilateur, comme M. S. B. suggère, mais la meilleure solution est tout simplement de corriger le code.
Merci beaucoup, je comprends vraiment maintenant, comment est-ce qu'il fonctionne. Deux choses 1) comment avez-vous calculé la mémoire nécessaire de 381 MO ?? 2) j'ai essayé d'utiliser la méthode COMMUNE dans la principale et la sous-routine de programme , mais à l'intérieur de la sous-routine, il m'a demandé de mettre une des dimensions spécifiques pour le MELE de la matrice (Qui est le seul de la matrice que j'ai besoin de commune), et il n'accepte pas utiliser les paramètres .. comment faire ?? merci
J'ai pensé que c'10 000 x 10 000 x 4 octets (entier 32 bits) = crédits de 400 000 000 octets = 390625 kilo-octets = environ 381 mo. Si votre défaut de type entier n'est pas en 32 bits, vous devez ajuster les valeurs en mémoire en conséquence.
Je ne suis pas trop familier avec le
COMMON
bloc, honnêtement. Je l'ai vu faire avec les paramètres externes des fichiers qui sont incluses dans le fichier de code, mais je ne suis pas tout à fait familier avec la façon dont c'est mis en place. Vous voudrez peut-être poser une autre question sur ce site pour voir si quelqu'un peut vous aider avec ça.OriginalL'auteur Daniel Pryden
N'est que le compilateur avoir une option pour mettre des tableaux sur le tas?
Vous pouvez essayer un autre compilateur, comme celui qui est toujours pris en charge. Fortran 95 compilateurs FORTRAN compiler 77. Il y a beaucoup de choix, y compris open source. Intel Visual Fortran, le successeur de Compaq Visual Fortran, a le tas option sur Windows & Mac OS X pour le placement automatique et temporaire des tableaux sur le tas.
ne va pas vous aider, car c'est pour les liens vers la mise en œuvre du sous-programme compilé séparément (souvent par un compilateur différent).
Comme Daniel l'a écrit, une déclaration d'INTERFACE n'aide pas -- ça décrit la sous-routine, elle ne change pas. Essayez de rechercher le manuel ou à l'aide d'une option relative à l'allocation de tas, ou de passer à une prise en charge actuellement du compilateur. Daniel suggestion de l'autre pour mettre les tableaux de grande taille dans un bloc COMMUN.
OriginalL'auteur M. S. B.
MELE est en fait un ensemble plus grand, puis NM: 10000 x 10000 x 4 x 4, contre 10001 x 100001 x 4 (en supposant que 4 octets, comme l'a fait Daniel) -- 1.49 GO contre 381 ko. MELE est déclarée dans votre programme principal et, à partir de vos tests, est acceptable, même si elle est plus grande. Donc, soit l'ajout NM pousse l'utilisation de la mémoire sur une limite (le total de ces deux tableaux est de 1,86 GO) ou la différence de la déclaration de questions. La taille de MELE est connu au moment de la compilation, que de NM seulement au moment de l'exécution, alors, probablement, le compilateur alloue de la mémoire différemment. Vraiment dans ce programme, la taille de NM est connu, mais dans la sous-routine les dimensions sont reçus comme des arguments, donc, pour le compilateur de la taille est inconnue. Si vous changer cela, le compilateur peut modifier la manière dont il alloue de la mémoire pour le NM et le programme peut s'exécuter. Ne passez pas les dimensions de NM comme arguments -- faire constantes. L'élégante serait de rendre un fichier inclus avec trois instructions de paramétrage de la configuration de la taille des matrices, puis de l'inclure inclure le fichier où il est nécessaire. Rapide et sale, comme un test, serait de répéter à l'identique les instructions de paramétrage dans la sous-routine, mais vous avez les mêmes informations deux fois, ce qui doit être changé deux fois si vous apportez des modifications. Dans les deux cas, vous devez supprimer le tableau des dimensions de la sous-routine des arguments à la fois l'appel et de la sous-routine de la déclaration, ou de l'utilisation des noms différents, parce que la même variable dans un sous-programme ne peut pas être un paramètre et un argument. Si cela ne fonctionne pas, déclarer NM dans le programme principal et de le passer en argument à la sous-routine.
Re le bloc COMMUN -- les dimensions doivent être connus au moment de la compilation, et ne peut donc pas être sous-routine arguments, les mêmes que ci-dessus. Comme Daniel l'a expliqué, de mettre le tableau en COMMUN serait certainement la cause de ne pas être sur la pile.
C'est au-delà de la norme du langage, la façon dont le compilateur fournit de la mémoire est un détail d'implémentation, "sous le capot". Donc la solution est en partie du domaine de la conjecture. Le manuel ou l'aide pour le compilateur peut avoir des réponses, par exemple, un tas de répartition.
OriginalL'auteur M. S. B.
Débordements de pile liées à la taille de la matrice est un signe d'avertissement qu'ils sont poussés ensemble sur la pile d'appel, au lieu de sur le tas. Avez-vous essayé de faire le tableau des variables
allocatable
? (Je ne suis pas sûr si cela est possible en F77)OriginalL'auteur Cecil Has a Name