6
votes

Comment puis-je dire si un pointeur de tableau Fortran a été attribué directement ou est associé à un autre objet?

Je travaille avec un code Fortran qui contient des pointeurs de tableau; Selon la saisie de l'utilisateur, ils pourraient être définis pour pointer sur un autre tableau avec l'instruction d'affectation => ou ils peuvent être directement alloués avec l'instruction allouer .

Ceci crée un problème pour libérer la mémoire à la fin du code, car dans le premier cas, je veux juste nullify le pointeur, tandis que dans le second cas, je dois offliger < / code> pour empêcher une fuite de mémoire. Le problème est que dans les deux cas associé renvoie vrai , donc je ne sais pas comment dire quel cas je suis sans garder la trace de cela manuellement. Puisqu'il y a beaucoup de points de tableau, je préférerais éviter de devoir le faire.

Y a-t-il un moyen simple de distinguer les deux cas?

Merci!


5 commentaires

Par "à la fin du code", quelle distance est-ce que vous voulez dire? Tout au long de l'exécution, je me soucie de fuites de mémoire, etc., mais à la fin de mon programme, il n'est plus ma responsabilité de s'assurer que tout soit rangé.


Je ne suis pas sûr de comprendre ce que vous voulez dire ... Je devrais sûrement viser que toute la mémoire allouée à être traitée avant que le programme se termine?


Je voulais dire que le programme (horrible): allouatable i; allouer (i); fin . Je ne ressens pas le moindre peu de culpabilité de ne pas avoir de de manière là-bas. Il y a des moments où je veux être responsable de la localisation, mais pas ici. Est la prémisse de votre question qu'il devrait y avoir une déclaration ? Mon premier commentaire était juste pour établir cela.


Ah Désolé, oui je me sens coupable! Il devrait y avoir un deallocate pour chaque allouer . Si je fais: entier, pointeur :: i (:); allouer i (5); annuler (i); fin alors je finirai avec un espace qui n'est pas distribué et également inaccessible au code.


Juste pour être clair, de peur que quiconque trébuche à travers cette question et se gênent aussi confus que moi - il n'y a absolument pas besoin de la mémoire explicitement libre, que ce soit en utilisant offliger ou nullify la fin d'un programme. À moins que votre O / S ne soit cassé, il allait récolter toute la mémoire allouée au programme lorsque le programme se termine. Ce serait une question différente si la souci de SOP était de récolter la mémoire à un autre point pendant l'exécution. Vous souhaitez également garder à l'esprit que les dernières éditions de la norme Fortran garantissent la classification lorsqu'un objet alloué est hors de portée.


3 Réponses :


7
votes

Cela ressemble à un désordre horrible. Je suppose que vous avez quelque chose comme ceci: xxx

et votre problème est la partie détruite. Si A pointe vers B , alors que vous souhaitez nullify , car vous devez conserver B . Mais si a ne pointe pas sur b , et que vous seul nullify it, vous obtenez une fuite de mémoire.

comme @ Ian-Bush souligne, vous pouvez vérifier si quelque chose est associé à autre chose, mais cela signifierait que vous devez comparer le pointeur avec toutes cibles possibles et vous prétendez que vous en avez beaucoup.

Une chose que vous pourriez essayer, mais cela est probablement encore pire une idée, est d'essayer de distribuer et d'utiliser son STAT = argument factice pour vérifier si le tableau a effectivement fonctionné. Veuillez noter que c'est un terrible hack, et je ne le suis que de travailler sur Intel, pas sur gfortran, mais ici ne fait rien: xxx

une méthode beaucoup meilleure serait probablement Pour remplacer vos pointeurs de tableau avec des types qui ont à la fois le pointeur et un drapeau de la manière dont il était associé. xxx

aucune de ces suggestions ne vous aidera pas alors Un autre pointeur à a puis essaie de le détruire . Dans ce cas, je suggère vraiment de repenser votre conception de votre projet entière.


1 commentaires

Merci beaucoup pour votre réponse. Vous avez complètement compris la situation. Je suis également arrivé à la conclusion que votre dernière méthode avec le drapeau supplémentaire est la seule voie à suivre (rien d'autre ne pointera les pointeurs, donc pas de problèmes là-bas). J'espérais pouvoir éviter cela, mais il semble qu'il n'y ait vraiment pas d'autre moyen.



4
votes

Comment compliqué est votre structure de données? C'est-à-dire combien de pointeurs sont associés simultanément à une seule cible à un moment donné? La norme Fortran est complètement silencieuse lorsqu'il s'agit de référencer la cible instanciée à l'aide de l'instruction allouer , c'est-à-dire qu'elle ne spécifie pas un mécanisme pour s'assurer que la mémoire cible est libérée lorsque tous les points de vue sont libérés. dissocié. La collection de déchets intégrée est précisément pourquoi l'attribut allouatable est préféré sur le pointeur attribue 99,9% du temps. Dans l'événement rare que vous devez absolument utiliser un pointeur et que sa cible est attribuée dans un autre sous-programme, puis a transmis la chaîne d'appels à une procédure différente, la possession de pointeur devient un cauchemar.

Si vous avez accès à un compilateur FORTRAN moderne (2008+), le module suivant pourrait être utile; FYI, les variables déclarées dans un module héritent automatiquement de l'attribut Enregistrer . La cible foo est une variable de module privé et ref_counter garde la trace du nombre de pointeurs associés à foo . En surchargeant la relocalisation Nous pouvons annuler en toute sécurité NULLIFY, NULLIFY + DealLocate. avec appelerallocate (quelque_ptr, dealloc_stat) xxx


1 commentaires

J'utilise une certaine construction similaire, mais à mon avis, la pleine puissance de la référence à compter que vous obtenez uniquement lorsque vous créez un nouveau type dérivé de référence et surcharger les missions et appliquer les finalisations (de la même manière que votre NULLIFY_PTR et POINT_AT_FOO.



3
votes

Peut-être que ce sera utile à quelqu'un. J'ai poussé à Github ma simple mise en œuvre de comptage de référence qui vous permet de suivre les références aux variables. Lorsque le nombre de références est 0, l'objet est automatiquement distribué. Link https://github.com/ladaf/fortran-refcount

Il est basé sur des idées de papier Voiture - Comptage de référence Implémentation dans Fortran 95/2003 et réserver Conception de logiciels scientifiques: la manière orientée objet . P>

La référence L'objet lui-même stocke un pointeur à un autre objet REFPTR code> qui stocke le pointeur sur les données elles-mêmes et le nombre de références qui l'indiquent. Les affectations sont surchargées de manière à ce que le nombre de références soit mis à jour. La finalisation des objets de référence soustrait des comptes de référence selon les besoins. P>

type(ref) :: a, b

a = 42
print *, "a:", a%value(0)

!this does not copy the value, it points the reference
b = a
print *, "b:", b%value(0)

!sets a to point to something new, b still points to 42
a = 2.3


0 commentaires