[fortran 77] tableaux locaux
Résolu
Char Snipeur
Messages postés
10112
Statut
Contributeur
-
cchristian Messages postés 928 Statut Membre -
cchristian Messages postés 928 Statut Membre -
Bonjour,
j'ai un problème assez théorique.
j'ai un fichier fortran contenant une subroutine contenant des tableaux locaux dimensionnés avec un entier pouvant varier au cours du programme.
Théoriquement, ceci est interdit en Fortran 77, mais gcc/gfortran le compile sans souci.
Ma question est alors : que fait le compilateur dans ce cas là ?
Il dimensionne le tableau à la bonne taille à chaque appel de la subroutine, ou il fait n'imoprte quoi et fait un dépassement de tableau ?
j'ai un problème assez théorique.
j'ai un fichier fortran contenant une subroutine contenant des tableaux locaux dimensionnés avec un entier pouvant varier au cours du programme.
Théoriquement, ceci est interdit en Fortran 77, mais gcc/gfortran le compile sans souci.
Ma question est alors : que fait le compilateur dans ce cas là ?
Il dimensionne le tableau à la bonne taille à chaque appel de la subroutine, ou il fait n'imoprte quoi et fait un dépassement de tableau ?
A voir également:
- [fortran 77] tableaux locaux
- Tchat locaux - Forum Vos droits sur internet
- "+33 1 87 21 77 77" - Forum Huawei
- Tchats locaux ✓ - Forum Logiciels
- Tchat en local - Forum Réseau
- Premier TP en Réseaux Locaux - Forum Études / Formation High-Tech
11 réponses
Bonjour,
Peux-tu poster les morceaux de codes où tu décris: le tableau, la variable qui le dimension et un cas d'utilisation du tableau.
Peux-tu poster les morceaux de codes où tu décris: le tableau, la variable qui le dimension et un cas d'utilisation du tableau.
par exemple (exemple théorique, simplifié) :
subroutine TEST(A,B)
IMPLICITE REAL*8 (A-H,O-Z)
COMMON DONNES/NBTAB/
DIMENSION A(*),B(*)
DIMENSION TABDYN(NBTAB)
DO 20 I=1,NBTAB
TABDYN(I)=a(i)+b(i)
20 continue
A=TABDYN(3)
B=TABDYN(5)
RETURN
Voilà en simplifier ce qui est fait.
Là, je ne suis pas en mesure de tester le code, mais théoriquement, le tableau étant alloué dynamiquement, le comportement n'est pas régi par le F77. Donc que fait le code ??
Si besoin, je tenterai de faire un autre petit démonstrateur si tu veux.
Merci.
subroutine TEST(A,B)
IMPLICITE REAL*8 (A-H,O-Z)
COMMON DONNES/NBTAB/
DIMENSION A(*),B(*)
DIMENSION TABDYN(NBTAB)
DO 20 I=1,NBTAB
TABDYN(I)=a(i)+b(i)
20 continue
A=TABDYN(3)
B=TABDYN(5)
RETURN
Voilà en simplifier ce qui est fait.
Là, je ne suis pas en mesure de tester le code, mais théoriquement, le tableau étant alloué dynamiquement, le comportement n'est pas régi par le F77. Donc que fait le code ??
Si besoin, je tenterai de faire un autre petit démonstrateur si tu veux.
Merci.
Heu ?
Toute piste est la bien venu.
Dans le message précédent, j'ai oublié de préciser que le common est initialisé dans un fichier C.
Voici un exemple complet :
main.c :
test.f :
Toute piste est la bien venu.
Dans le message précédent, j'ai oublié de préciser que le common est initialisé dans un fichier C.
Voici un exemple complet :
main.c :
struct commun
{
int nbtab;
};
void test(void);
extern struct commun donnee;
int main()
{
donnee.nbtab=10;
int i;
for(i=0;i<100;++i)
test();
return 0;
}
test.f :
subroutine test()
integer nbtab,i
common /donnee/nbtab
real*8 tab
dimension tab(nbtab)
do 10 i=1,nbtab
tab(i)=tab(i)+1.D0
10 continue
return
end
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Bonjour,
Voici quelques remarques faites à partir de ton 1er exemple quelque peu remanié:
Il semble par conséquent que l'aspect dynamique soit "géré" convenablement par le poduit Fortran 77 (Force 2.0) puisque le tableau TABDYN est chargé et exploré sans problème avec un nombres de postes différents à chaque appel de la subroutine dans laquelle il est décrit (la place mémoire doit donc être réservée dynamiquement). Sinon je ne vois pas très bien comment le compilateur pourrait s'en tirer.
Qu'en penses-tu ?
Voici quelques remarques faites à partir de ton 1er exemple quelque peu remanié:
C Cinématique de fonctionnement:
C On déclare 2 tableaux S_A et S_B de 20 postes chacun. Après une
C initialisation à la valeur 1 de leur 12 premiers postes, ces 2
C tableaux sont passés à la subroutine TEST.
C La première fois en délimitant le nombre de postes S_NBTAB avec
C une valeur (10) inférieure à la taille des tableaux:
C Résultats d'exécution (1er appel subroutine):
C A ( 1) : 1.+B ( 1) : 1. = TABDYN( 1) : 2.
C A ( 2) : 1.+B ( 2) : 1. = TABDYN( 2) : 2.
C A ( 3) : 1.+B ( 3) : 1. = TABDYN( 3) : 2.
C A ( 4) : 1.+B ( 4) : 1. = TABDYN( 4) : 2.
C A ( 5) : 1.+B ( 5) : 1. = TABDYN( 5) : 2.
C A ( 6) : 1.+B ( 6) : 1. = TABDYN( 6) : 2.
C A ( 7) : 1.+B ( 7) : 1. = TABDYN( 7) : 2.
C A ( 8) : 1.+B ( 8) : 1. = TABDYN( 8) : 2.
C A ( 9) : 1.+B ( 9) : 1. = TABDYN( 9) : 2.
C A ( 10) : 1.+B ( 10) : 1. = TABDYN( 10) : 2.
C Le résultat est évidemment cohérent.
C la seconde fois S_NBTAB est forcé avec une valeur (25) supérieure
C à la taille des tableaux S_A et S_B (20). Les postes 13 à 20
C sont renseignés avec la valeur 8 pour le tableau S_A et avec la
C valeur 9 pour le tableau S_B avant l'appel à la subroutine TEST.
C Les postes 21 à 25 de TABDYN sont renseignés avec la logique du
C sous-programme TEST, chacun à la valeur 999,
C Résultats d'exécution (2ème appel subroutine):
C A ( 1) : 1.+B ( 1) : 1. = TABDYN( 1) : 2.
C A ( 2) : 1.+B ( 2) : 1. = TABDYN( 2) : 2.
C A ( 3) : 1.+B ( 3) : 1. = TABDYN( 3) : 2.
C A ( 4) : 1.+B ( 4) : 1. = TABDYN( 4) : 2.
C A ( 5) : 1.+B ( 5) : 1. = TABDYN( 5) : 2.
C A ( 6) : 1.+B ( 6) : 1. = TABDYN( 6) : 2.
C A ( 7) : 1.+B ( 7) : 1. = TABDYN( 7) : 2.
C A ( 8) : 1.+B ( 8) : 1. = TABDYN( 8) : 2.
C A ( 9) : 1.+B ( 9) : 1. = TABDYN( 9) : 2.
C A ( 10) : 1.+B ( 10) : 1. = TABDYN( 10) : 2.
C A ( 11) : 1.+B ( 11) : 1. = TABDYN( 11) : 2.
C A ( 12) : 1.+B ( 12) : 1. = TABDYN( 12) : 2.
C A ( 13) : 8.+B ( 13) : 9. = TABDYN( 13) : 17.
C A ( 14) : 8.+B ( 14) : 9. = TABDYN( 14) : 17.
C A ( 15) : 8.+B ( 15) : 9. = TABDYN( 15) : 17.
C A ( 16) : 8.+B ( 16) : 9. = TABDYN( 16) : 17.
C A ( 17) : 8.+B ( 17) : 9. = TABDYN( 17) : 17.
C A ( 18) : 8.+B ( 18) : 9. = TABDYN( 18) : 17.
C A ( 19) : 8.+B ( 19) : 9. = TABDYN( 19) : 17.
C A ( 20) : 8.+B ( 20) : 9. = TABDYN( 20) : 17.
C TABDYN( 21) : 999.
C TABDYN( 22) : 999.
C TABDYN( 23) : 999.
C TABDYN( 24) : 999.
C TABDYN( 25) : 999.
C Le résultat est LUI AUSSI cohérentpour 25 postes de TABDYN.
C Par contre si dans la subroutine TEST on tente de renseigner un
C NBTAB + 1 => (25 + 1)ième poste le programme plante:
C DO 20 I = 1, NBTAB + 1 ! Pour test de débordement.
C le programme plante... C'EST NORMAL !
PROGRAM TEST0
IMPLICIT NONE
COMMON /DONNES/ S_NBTAB ! Variable de passation.
INTEGER S_NBTAB ! Borne tableaux.
INTEGER K
DIMENSION S_A (20)
REAL*8 S_A
DIMENSION S_B (20)
REAL*8 S_B
DATA (S_A (K), K = 1, 12, 1) / 12 * 1 / !12 postes des Tableaux
DATA (S_B (K), K = 1, 12, 1) / 12 * 1 / !initialisés à 1.
S_NBTAB = 10
CALL TEST (S_A, S_B) ! 1er. Appel Subroutine.
S_A (13) = 8
S_B (13) = 9
S_A (14) = 8
S_B (14) = 9
S_A (15) = 8
S_B (15) = 9
S_A (16) = 8
S_B (16) = 9
S_A (17) = 8
S_B (17) = 9
S_A (18) = 8
S_B (18) = 9
S_A (19) = 8
S_B (19) = 9
S_A (20) = 8
S_B (20) = 9
S_NBTAB = 25
CALL TEST (S_A, S_B) ! 2ème Appel Subroutine.
END
SUBROUTINE TEST (A, B)
IMPLICIT REAL*8 (A-H, O-Z)
COMMON /DONNES/ NBTAB
DIMENSION A(*), B(*)
DIMENSION TABDYN (NBTAB)
REAL*8 TABDYN
C DO 20 I = 1, NBTAB + 1 ! Pour test de débordement.
DO 20 I = 1, NBTAB, 1
IF ( I > 20 ) THEN
TABDYN (I) = 999.00
ELSE
TABDYN (I) = A (I) + B (I)
END IF
20 CONTINUE
DO 30 I = 1, NBTAB, 1 ! Boucle pour contrôles.
IF ( I > 20 ) THEN
PRINT *, ' TABDYN(', I,') : ', TABDYN(I)
ELSE
PRINT *, 'A (', I,') : ', A (I), '+', 'B (', I,') : ', B (I)
S ,' = TABDYN(', I,') : ', TABDYN(I)
END IF
30 CONTINUE
RETURN
END
Il semble par conséquent que l'aspect dynamique soit "géré" convenablement par le poduit Fortran 77 (Force 2.0) puisque le tableau TABDYN est chargé et exploré sans problème avec un nombres de postes différents à chaque appel de la subroutine dans laquelle il est décrit (la place mémoire doit donc être réservée dynamiquement). Sinon je ne vois pas très bien comment le compilateur pourrait s'en tirer.
Qu'en penses-tu ?
Avec mon second test, j'ai exploré de grand tableaux (plus grand que ce qu'il pourrai mettre comme taille par défaut), sans souci.
Je pense en effet que le compilateur (gcc ou gfortran) gère correctement l'allocation dynamique du tableau. Je suis rassuré, le programme ne doit pas faire d'erreur. La réponse exact à ce problème doit se trouver dans le code assembleur généré, mais je n'ai rien compris à ce charabia :*)
En revanche, est-ce que cette façon de faire est présente dans le standard strict fortran 77 ?
Une de nos préoccupation est la portabilité, il faut donc se conformer au maximum au standard pour éviter les soucis.
Merci pour ton aide.
Je pense en effet que le compilateur (gcc ou gfortran) gère correctement l'allocation dynamique du tableau. Je suis rassuré, le programme ne doit pas faire d'erreur. La réponse exact à ce problème doit se trouver dans le code assembleur généré, mais je n'ai rien compris à ce charabia :*)
En revanche, est-ce que cette façon de faire est présente dans le standard strict fortran 77 ?
Une de nos préoccupation est la portabilité, il faut donc se conformer au maximum au standard pour éviter les soucis.
Merci pour ton aide.
Bonjour,
Je pense que tu trouveras des éléments de réponse supplémentaires sur ce site:
http://www.fortran.com/fortran/F77_std/rjcnf0001-sh-5.html#sh-5.5
plus particulèrement au paragraphe (situé au 3/4 de la page) :
5.5.1 Adjustable Arrays and Adjustable Dimensions.
Je pense que tu trouveras des éléments de réponse supplémentaires sur ce site:
http://www.fortran.com/fortran/F77_std/rjcnf0001-sh-5.html#sh-5.5
plus particulèrement au paragraphe (situé au 3/4 de la page) :
5.5.1 Adjustable Arrays and Adjustable Dimensions.
Merci pour le lien.
Par contre, je n'ai pas vraiment compris. De ce que j'ai compris, ça semble permis.
Pour l'instant, nous allons dimensionner nos tableaux avec une constante, en attendant de trouver une réponse clair.
Par contre, je n'ai pas vraiment compris. De ce que j'ai compris, ça semble permis.
Pour l'instant, nous allons dimensionner nos tableaux avec une constante, en attendant de trouver une réponse clair.
Bonsoir,
Pour l'instant, nous allons dimensionner nos tableaux avec une constante, en attendant de trouver une réponse clair
Ca semble plus sage en effet car il y a certaines choses qui m'étonnent comme par exemple, en modifiant le programme (lignes marquées ! <======= Modif), faire passer le tableau "TABDYN" de la partie Main à la subroutine. Le programme continue de fonctionner sans problème bien que S_TABDYN est décrit en Main de taille inférieure à son homologue TABDYN décrit dans la subroutine. Alors que la règle suivante :
The size of the adjustable array must be less than or equal to the size of the array that is its corresponding actual argument
est enoncée au paragraphe :
6.1.1.1 Adjustable Arrays de
http://www.helsinki.fi/atk/unix/dec_manuals/cf77au/olrm0121.htm
Par contre quand je compile et je lance une exécution du même programme avec l'IDE Silverfrost FTN95 il part en abend avec le message :
Runtime error from program:c:\docume~1\christ~1\mesdoc~1\b-fort~1.fil\test0.exe
Run-time Error
Attempt to call a routine with argument number three containing too few array elements
TEST - in file test0.f at line 101 [+00af]
TEST0 - in file test0.f at line 79 [+0066]
Ah ces compilateurs ! Le moins que l'on puisse dire, c'est que "ce n'est pas portable"
A noter que la version initiale de mon programme (hors <======= Modif) passe sans problème dans les deux environnements.
Pour l'instant, nous allons dimensionner nos tableaux avec une constante, en attendant de trouver une réponse clair
Ca semble plus sage en effet car il y a certaines choses qui m'étonnent comme par exemple, en modifiant le programme (lignes marquées ! <======= Modif), faire passer le tableau "TABDYN" de la partie Main à la subroutine. Le programme continue de fonctionner sans problème bien que S_TABDYN est décrit en Main de taille inférieure à son homologue TABDYN décrit dans la subroutine. Alors que la règle suivante :
The size of the adjustable array must be less than or equal to the size of the array that is its corresponding actual argument
est enoncée au paragraphe :
6.1.1.1 Adjustable Arrays de
http://www.helsinki.fi/atk/unix/dec_manuals/cf77au/olrm0121.htm
Par contre quand je compile et je lance une exécution du même programme avec l'IDE Silverfrost FTN95 il part en abend avec le message :
Runtime error from program:c:\docume~1\christ~1\mesdoc~1\b-fort~1.fil\test0.exe
Run-time Error
Attempt to call a routine with argument number three containing too few array elements
TEST - in file test0.f at line 101 [+00af]
TEST0 - in file test0.f at line 79 [+0066]
Ah ces compilateurs ! Le moins que l'on puisse dire, c'est que "ce n'est pas portable"
A noter que la version initiale de mon programme (hors <======= Modif) passe sans problème dans les deux environnements.
PROGRAM TEST0
IMPLICIT NONE
COMMON /DONNES/ S_NBTAB ! Variable de passation.
INTEGER S_NBTAB ! Borne tableaux.
INTEGER K
DIMENSION S_A (20)
REAL*8 S_A
DIMENSION S_B (20)
REAL*8 S_B
C DIMENSION S_TABDYN (1:1) ! <======= Modif.
C REAL*8 S_TABDYN ! <======= Modif.
DATA (S_A (K), K = 1, 12, 1) / 12 * 1 / !12 postes des Tableaux
DATA (S_B (K), K = 1, 12, 1) / 12 * 1 / !initialisés à 1.
S_NBTAB = 10
CALL TEST (S_A, S_B)
C CALL TEST (S_A, S_B, S_TABDYN) ! <======= Modif.
S_A (13) = 8
S_B (13) = 9
S_A (14) = 8
S_B (14) = 9
S_A (15) = 8
S_B (15) = 9
S_A (16) = 8
S_B (16) = 9
S_A (17) = 8
S_B (17) = 9
S_A (18) = 8
S_B (18) = 9
S_A (19) = 8
S_B (19) = 9
S_A (20) = 8
S_B (20) = 9
S_NBTAB = 25
CALL TEST (S_A, S_B)
C CALL TEST (S_A, S_B, S_TABDYN ) ! <======= Modif.
END
SUBROUTINE TEST (A, B)
C SUBROUTINE TEST (A, B,TABDYN) ! <======= Modif.
IMPLICIT REAL*8 (A-H, O-Z)
COMMON /DONNES/ NBTAB
DIMENSION A(*), B(*)
DIMENSION TABDYN (1:NBTAB)
REAL*8 TABDYN
DO 20 I = 1, NBTAB, 1
IF ( I > 20 ) THEN
TABDYN (I) = 999.00
ELSE
TABDYN (I) = A (I) + B (I)
END IF
20 CONTINUE
DO 30 I = 1, NBTAB, 1 ! Boucle pour contrôles.
IF ( I > 20 ) THEN
PRINT *, ' TABDYN(', I,') : ', TABDYN(I)
ELSE
PRINT *, 'A (', I,') : ', A (I), '+', 'B (', I,') : ', B (I)
S ,' = TABDYN(', I,') : ', TABDYN(I)
END IF
30 CONTINUE
RETURN
END
Salut.
lorsque tu passe le tableau en argument, il est en effet étonnant qu'il n'y ait pas une erreur de segmentation. Je connait mieux le C, et j'ai déjà eu des cas en C, où l'écriture en dehors du tableau ne posait pas de souci. En fait, ce n'est pas parceque tu écris ou lit en dehors du tableau que tu génère une erreur de segmentation, il faut lire et écrire en dehors de la mémoire allouée au programme. Il est probable qu'avec un tableau plus grand ou aléatoirement, il plante.
C'est pas carré tout ça...
lorsque tu passe le tableau en argument, il est en effet étonnant qu'il n'y ait pas une erreur de segmentation. Je connait mieux le C, et j'ai déjà eu des cas en C, où l'écriture en dehors du tableau ne posait pas de souci. En fait, ce n'est pas parceque tu écris ou lit en dehors du tableau que tu génère une erreur de segmentation, il faut lire et écrire en dehors de la mémoire allouée au programme. Il est probable qu'avec un tableau plus grand ou aléatoirement, il plante.
C'est pas carré tout ça...