Re: [問題] 變數自行改變

看板Fortran作者 (片翼碎夢)時間4年前 (2019/09/15 11:03), 4年前編輯推噓7(7032)
留言39則, 6人參與, 最新討論串2/2 (看更多)
※ 引述《sven1130 (綠色貍貓)》之銘言: : 如題 : 這個問題困擾我很久了 : 本魯使用visual studio : 目前我這個程式的架構 : 是由C++去呼叫一個for的dll : 然後跑dll裡面眾多的subroutine : 重點來了 : 當我跑了六次這個迴圈的時候 : 在跑完!****************************************** : 標示的該行後 : 有一個於這個迴圈都沒有出現的參數NNE(7) : 會自動變為一個很奇怪的數字 : 原本為14跑完後變為一個極大的數字 : 但該行甚至這個迴圈 與參數NNE應該是一點關係也沒有 : 為何會這樣 求解 先謝過大家了 : 附圖 : https://imgur.com/7kf4X9E
: 按一下F11逐步執行後變成 : https://imgur.com/gznxEKU
: 完全沒有道理啊@@ : 附上該迴圈 : DO I=L,1,-1 : OPEN(60,FILE='MANNING.DAT',STATUS='OLD') : OPEN(61,FILE='NCCHECH.OUT',STATUS='UNKNOWN') : READ(60,1002) NC : 1002 FORMAT(5X,F8.5) : CMN(I,J)=NC : !****************************************** : WRITE(61,*)"CMN(",I,",",J,")",CMN(I,J) : !****************************************** : !將CMN寫入NCCHECH.OUT : READ(IIN,1004) NDS(I,J),XL,XR,LL,LR,LC : 1004 FORMAT(8X,F8.0,2F8.2,3F8.0) : C DIST1(I,J)=(LL+LC+LR)/3.0 : DIST1(I,J)=(LL+LC+LR)/3.0*3 : KK=NDS(I,J) : WRITE(5,1006)J,I,NDS(I,J),XL,XR,DIST1(I,J),CMN(I,J) : 1006 FORMAT(//5X,I3,2X,I3,4X,F8.0,2X,F8.2,2X,F8.2,2X,F8.2,2X,F8.4) : READ(IIN,1008)(AY(II,I,J),AX(II,I,J),II=1,KK) : 1008 FORMAT(2X,F6.2,9F8.2) : WRITE(5,1978)(AY(II,I,J),AX(II,I,J),II=1,KK) : 1978 FORMAT(2X,F6.2,9F8.2) : Z(I,J)=100.0 : DO 1010 II=1,KK : IF(AX(II,I,J).EQ.XL) N1(I,J)=II : IF(AX(II,I,J).EQ.XR) N2(I,J)=II : IF(Z(I,J).GE.AY(II,I,J)) THEN : Z(I,J)=AY(II,I,J) : Z919(I,J)=AY(II,I,J) : END IF : 1010 CONTINUE : WRITE(5,1012) N1(I,J),N2(I,J),Z(I,J) : c WRITE(*,1012) N1(I,J),N2(I,J),Z(I,J) : 1012 FORMAT(5X,I8,2X,I8,2X,F8.2) : END DO 經過和認識的工程師討論後,我確定有某個以FORTRAN開始學的人不會發生 但是從其他語言過來的人可能會沒注意到的問題 那就是,FORTRAN的副程式(subroutine)和函式(function) 並不是單純地call by value而已,call此程式的程式內的變數也會被改變 舉個例子: program main implicit none integer :: var var = 10 call FortranVar(var) write(*,*) var stop end subroutine FortranVar(var2) !var2就是在FortranVar內的var implicit none integer :: var2 var2 = var2**2 return end 出來的結果會是100,其他程式語言應該會變成10(不變) 看到變數出問題時我有想到這個可能,可是因為這對從FORTRAN開始學的人來說很正常 就忽略這個可能原因了 不過,後來想到當我走出FORTRAN看到別的程式語言都是call by value後很不能接受 所以反過來說,其他語言的使用者在接觸到FORTRAN時不知道這點的可能性其實不小 重點是,要注意到這代表所有在副程式和函式內變更的值都會影響回叫出他們的程式 所以有在用Fortran的人,至少我自己在寫的時候 只要程式很大,習慣性會寫程式碼把數值複製下來 放在別的變數後,將原本的變數原封不動地還回去(也就是自己寫成call by value) 寫了這麼多,結論是 我懷疑問題根本是出在那一坨subroutine和function之中 可能需要把程式碼複製到word上搜尋有NNE的地方 把每一行有關於NNE的程式碼都找出來慢慢看了 -- 即使祂每天因人們而墮入滾燙的熱水,麵神也不會製造出地獄來懲罰不信仰祂的人 我們崇拜麵神是出於敬佩與感謝,與生前死後諸利益得失皆無任何關係 阿麵~ -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 42.77.1.161 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Fortran/M.1568516631.A.2F8.html ※ 編輯: fragmentwing (42.77.1.161 臺灣), 09/15/2019 11:14:53 ※ 編輯: fragmentwing (42.77.1.161 臺灣), 09/15/2019 11:17:37

09/15 13:37, 4年前 , 1F
好的 謝謝f大特地回一篇解惑~
09/15 13:37, 1F

09/15 13:50, 4年前 , 2F
不過在我的印象之中 NNE這個矩陣是dimension NNE(NE) 而
09/15 13:50, 2F

09/15 13:50, 4年前 , 3F
NE我改用在另一個副程式中寫入數值(原版用全域常數寫死)
09/15 13:50, 3F

09/15 13:50, 4年前 , 4F
但NNE這個變數讀取的時間與出錯的時機 都是在同一個副
09/15 13:50, 4F

09/15 13:50, 4年前 , 5F
程式裡面@@
09/15 13:50, 5F

09/15 14:12, 4年前 , 6F
等等 你改變寫法後 nne有改用allocate 去宣告嗎
09/15 14:12, 6F

09/15 14:12, 4年前 , 7F
因為照你的說法 好像是延用原本的陣列宣告?
09/15 14:12, 7F

09/15 14:14, 4年前 , 8F
但是照理來說 這種方式沒有改用動態陣列 編譯器不會
09/15 14:14, 8F

09/15 14:14, 4年前 , 9F
給過才對
09/15 14:14, 9F

09/15 14:27, 4年前 , 10F
好 回去複習以前寫的 應該是用(:)或是在副程式內自
09/15 14:27, 10F

09/15 14:27, 4年前 , 11F
己宣告parameter也都可 但我不清楚樓主是不是有用後
09/15 14:27, 11F

09/15 14:27, 4年前 , 12F
者的寫法
09/15 14:27, 12F

09/15 14:40, 4年前 , 13F
誒這我不大確定耶 近期我把所有東西梳理過一遍 再跟各位
09/15 14:40, 13F

09/15 14:40, 4年前 , 14F
先進報告
09/15 14:40, 14F

09/15 14:40, 4年前 , 15F
如果是編譯的部分 我想dll能生出來 應該就沒有問題吧 至
09/15 14:40, 15F

09/15 14:40, 4年前 , 16F
少不會出這種錯哈哈
09/15 14:40, 16F

09/16 19:59, 4年前 , 17F
新的fortran可以用intent宣告,不過這有時會有其他問題。
09/16 19:59, 17F

09/17 18:14, 4年前 , 18F
Fortran在傳遞參數時,是傳遞這個變數的記憶體位址
09/17 18:14, 18F

09/17 18:26, 4年前 , 19F
Fortran 2003 後如果副程式中的參數加上 VALUE attribu
09/17 18:26, 19F

09/17 18:27, 4年前 , 20F
VALUE attribute,則傳入數值,而不是位址,
09/17 18:27, 20F

09/17 18:27, 4年前 , 21F
上面的例子中主程式中的 var 就不會改變,還是 10
09/17 18:27, 21F

09/17 18:33, 4年前 , 22F
一般的情況是 call by reference,改為 call by value
09/17 18:33, 22F

09/17 22:41, 4年前 , 23F
intent90就有 可是那個對於本來的fortran使用方式而
09/17 22:41, 23F

09/17 22:41, 4年前 , 24F
言很難搞
09/17 22:41, 24F

09/17 22:43, 4年前 , 25F
話說原來到2003都跟別人反著來 別人都特別用指標才
09/17 22:43, 25F

09/17 22:43, 4年前 , 26F
傳址 就fortran預設傳址XD 然後搞得Fortran的指標有
09/17 22:43, 26F

09/17 22:43, 4年前 , 27F
點微妙
09/17 22:43, 27F

01/30 06:59, 5年前 , 28F
解決了嗎?看起來是IJ過大或是CMN宣告問題
01/30 06:59, 28F

02/18 17:49, 5年前 , 29F
一直忘記更新 解決了 把很長的程式碼切成很多分份就可以
02/18 17:49, 29F

02/18 17:49, 5年前 , 30F
了 原因不明@@
02/18 17:49, 30F

05/20 08:31, , 31F
FORTRAN 自始應該就是傳址的, 而且 Fortran 據說還是最古老
05/20 08:31, 31F

05/20 08:33, , 32F
的語言. 在 Fortran 77 及以前, 好像也沒有 public 變數,
05/20 08:33, 32F

05/20 08:35, , 33F
Fortran 90 多了很多特性, 不過傳址, 變數基本為 local 仍
05/20 08:35, 33F

05/20 08:36, , 34F
沒有變, 只是可以宣告 public 變數. 有些書把 COMMON 區當
05/20 08:36, 34F

05/20 08:38, , 35F
作 public 變數看待其實是不對的, common 只是位址共用, 其
05/20 08:38, 35F

05/20 08:40, , 36F
中變數仍要各程式單元宣告. Fortran 的 pointer 有點像
05/20 08:40, 36F

05/20 08:41, , 37F
python 的變數名稱 (所以 python 的程式單元 argument 的傳
05/20 08:41, 37F

05/20 08:43, , 38F
遞另成一格,既不是傳值也不是傳址, 或說有時像傳值有時又像
05/20 08:43, 38F

05/20 08:44, , 39F
傳址).
05/20 08:44, 39F
文章代碼(AID): #1TVQeNBu (Fortran)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
文章代碼(AID): #1TVQeNBu (Fortran)