MSGID: 0:0/0 385D0290
-KEY: F6E82AE0
>int func1(void)
>{
> int i;
> :
> :
> return i;
>}
>
>int i;
>
>void func2(void)
>{
> :
>}
----------------------------------------------------------------------
由於回文的高手有好幾位,
而各位回文時引出的引言很長,
所以將各位的文整理一下一併在此回了,
懇請見諒.
----------------------------------------------------------------------
From: GOLDMEMBER.bbs@bbs.cs.nctu.edu.tw (㊣金大支大壽,六六大支!)
>※ 引述《maru8888@bbs.emerald.net.tw (marujoung)》之銘言:
>> 我知道本板的高手很多,
>> 為什麼都保持沉默呢? 我已等了近兩個月了...
>
>你講得太簡單,
>依照你提供的架構仿寫程式,無法複製錯誤,
>當然也就無法幫你解釋錯誤何在。
>
>簡單的想法是TC++或許有bug,你可換用Dev-CPP重新編譯試試。
TC++ 確實 bug 很多, 但要我換 compiler....(面有難色)
這就好像開了十幾年的老爺車問題很多, 它的問題只有我知道,
而我也習慣爆出問題時該如何因應了, 例如打顆蛋到水箱,
今天換台勞斯萊斯,
很棒! 但故障時我就不會修理了...
除了 TC++ 外 C compiler 我用 BCB,
但為何本程式堅持用 TC++ 呢?
因為程式中有攔截硬體中斷的動作, 而 BCB 不讓我這麼做.
----------------------------------------------------------------------
From: oohay.bbs@ptt.cc (五黑)
>1. 別人不見得學過所謂 "大拇指原則"
所謂大拇指原則, 就是函式內容以一頁為原則.
>2. 為什麼你會猜測是func1把區域變數i當作全域變數使用? 憑什麼說違反視野?
大哥! 我從頭到尾都沒這樣說喔! 煩再閱前文,
我只是移動了一下 int i 的位置就解決了,
so 好像是在視野的使用上出了問題...
我好像找到解釋的理由了, 煩見信尾.
>3. 出錯,錯誤訊息講什麼,指向哪一行,看清楚了在做除錯動作.
大哥! 小弟我是真的有難題要求助, 不是來吵架的, 幹嘛講話那麼衝!
小弟向來以除錯技術佳自豪, 這回抓不出原因是學藝不精, 對視野瞭解不夠.
compiler 根本說沒錯, 是執行結果不是我想的.
>或許你可以把全域變數i移到最前面,但也別刪掉func1內的區域變數i.
但事實是我改成這麼做後問題就解決了耶?
仔細品味兄台這句話,
猜想兄台的想法是外在變數在進入 func1 前作用了,
但一進入 func1 便被 auto 變數遮蓋,
離開 func1 進入 func2 時 i 又變回外在變數, 是吧?
噫! 好像有道理喔! 可是我不敢再試,
因目標(資料庫)太大無法備份, 再出狀況會很麻煩.
而我的想法(拿掉 auto)是:
func1 及 func2 統一共用外在變數 int i,
由名稱叫 i 而非有意義的單字便知它只是個暫用的變數, 例如迴圈.
當 i 離開 func1 時它的值是什麼已不重要,
因為進入 func2 時值會重設,
同理當 i 離開 func2 時它的值是什麼不重要,
因為再進入 func1 時值會重設.
結論: 也許 bug 真的被您抓到了, 但很冒險, 我不敢試;
我的想法很簡單, 但較安全, 且通過了事實證明.
也許您會問: 既然堅持自己的想法, 幹嘛問我們!
程式的 bug 已用我的方式解決了, 小弟我只是想知道當初錯誤的原因.
----------------------------------------------------------------------
From: kenlo1980.bbs@ptt.cc (那裡沒有湯匙)
>不是高手保持沉默,而是他們沒辦法回答你的問題。
>因為你的問題比較像是 dependency on compiler / os。
>已經是高手等級的人,
>當菜鳥練功時用的 TC 版本大多為 2.01 左右,也就是十餘年前。
>而且現在多半已經不用 TC 了,
>因此無法複製你的 bug,自然無法回答你的問題。
>
>: 期間我把施大師的著作拿出來 k 了,
>: 疑惑仍在:
>: func1 內的 int i 是在執行時以堆疊配置,
>: 而夾在 func1 和 func2 間的 int i 早在編譯時就配置好了,
>
>我大概有十年以上沒碰 TC,當然我並不是高手,
>但在我印象中 borland 的 compiler 對變數會分已初始化跟未初始化的資料,
>分別置放在 BSS 與 DATA 節區,而你的 i 都是屬於未初始化的資料。
>如果我沒記錯,在 Boralnd C Compiler 的 memory model 中,
>small 的 bss, data 跟 stack 好像是在一起的。
>我猜你大概是用 tiny 或 small 的 memory model。
>你有沒有試過改用 large 來 compiler?
呵您猜錯了, 本程式只能用 huge 編譯, 因為 DATA 段太大了,
大到我原本超過 64K, 但 compiler 不讓我這麼用,
我只好拼命減肥使 DATA 小於 64K --
說到這裡,
坊間(十幾年前啦)的書都說 huge 的 DATA 段可超過 64K,
但我的經驗是六種 model 都不能超過 64K,
於是我編譯的習慣是:
若要寫成 *.com 用 tiny 模式,
小程式用內定的 small,
大程式則實驗一下,
拿本程式來說, large model 也能過關, 但實際下去跑時就會出錯
>或者觀察 compiler 出來之後各變數的置放方式?
>: 兩者在 RAM 中的位置並不相同, 應該不會干擾才對啊?
>我只能說你太武斷了,為什麼不把整個 memory map 弄出來看呢?
抱歉小弟才疏學淺, 這招我就不會了, ^^"
debug -T ? :P
我知道有這種工具, 但我手邊沒有.
----------------------------------------------------------------------
From: sjgau.bbs@ptt.cc (sjgau)
>: 我知道本板的高手很多,
>: 為什麼都保持沉默呢? 我已等了近兩個月了...
>: 期間我把施大師的著作拿出來 k 了,
>: 疑惑仍在:
>你的問題沒有得到回覆,除了你沒有po 完整的程式,
>比較不容易知道你的問題在哪裡之外,
>問問題的技巧 也是很重要。
>
>問對問題之後,一切就好辦。
我沒 po 文除了原始程式大過 64K 外,
很多列的列長超過 80 bytes, 你叫我怎麼貼!?
這個程式是用來篩選資料庫中的某些不良資料,
數年前所寫, 運作良好,
近日為了強化一項功能時發現程式太亂自己都看不懂當年是怎麼想的,
於是開始將之「大拇指原則」化,
如 func2 就切割成十幾個函式;
本來 func1 和 func2 各有一個 auto 變數 int i 互不干擾,
現在 func2 被切割了, 它的 int i 勢必升級為外在變數,
於是將之放在 func1 後 func2 前,
結果出差錯了: 某些資料類別全部被砍!
**********************************************************************
關於程式錯誤的原因, (是不是我不知道喔)我是這麼解釋:
依施威銘大師的分類, 長得最像的寫法是:
func1 內的 i 應寫為 extern int i
理由是 func1 和 func2 間的那個 int i 是「定義」不是「宣告」,
書中曾提過我這種寫法的變數名稱若相同會干擾(我忘了在哪一頁看到的)
func1 內寫 int i 是企圖在外在變數 int i 視野之前使用後者,
所以應該是個「宣告」; 既然是宣告就該加上 extern.
於是, 本程式的寫法是種妾身未明的寫法,
compiler 分不清它是「宣告」還是「定義」,
也許不同的 c compiler 處理方式不同,
TC++ 選擇放它過關, 但後果自負.
而我的改法,
即把 func1 內的 int i 去掉, 外在變數 int i 移到 func1 前,
因為該處前面的函式都沒叫用 int i,
而該處後面的函式知道 i 是共用的,
避開了搶飯碗的情形, 所以就執行對了.
--- 本站可傳檔、聊天、寫信喔 !
* Origin: 翡翠王國資訊站(BBS) [站址: 203.204.191.217] (0:0/0)