• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            清風(fēng)竹林

            ぷ雪飄絳梅映殘紅
               ぷ花舞霜飛映蒼松
                 ----- Do more,suffer less

            Solmyr 的小品文系列之九:次序問(wèn)題

            “zero 幫幫忙吧 ~~ ”

            聽(tīng)到這個(gè)充滿(mǎn)誠(chéng)意的聲音,zero 垮下了雙肩,感覺(jué)自己處于徹底崩潰的邊緣 ———— 幾個(gè)月來(lái),每次 pisces 遇到什么不能解決的問(wèn)題,總是用這個(gè)開(kāi)場(chǎng)白來(lái)求 zero,而后 zero 就不得不面對(duì)各式各樣匪夷所思的古怪問(wèn)題。

            “她怎么就能弄出那么多錯(cuò)誤來(lái)呢?” zero 在心中哀嘆。他苦著臉,問(wèn)道:“你就不能放過(guò)我去找 Solmyr 么?”

            “可是 Solmyr 指定你來(lái)幫助我們的呀!”

            “ …… 好吧,說(shuō)說(shuō)是什么問(wèn)題”,zero 一邊在心里再次痛罵了 Solmyr 一百遍,一邊做好了再次面對(duì)奇怪錯(cuò)誤的準(zhǔn)備。

            “嗯,這里有一段代碼,是讀取配置文件信息的。現(xiàn)在只是個(gè)框架,將來(lái)可能需要讀好些配置文件,而且可能放在不同目錄下,所以這里我用一些 string 對(duì)象保存路徑和文件名,然后用 fopen 打開(kāi)。” 說(shuō)著,pisces 調(diào)出了一個(gè) cpp 文件:

            #include <cstdio>
            #include <string>
            #include "config.h"    // 頭文件,定義了存放配置信息的結(jié)構(gòu)
                                          // 并包含 read_cfg 函數(shù)的聲明

            using namespace std;

            const string path = "./cfg/";
            const string name = "system.cfg";

            // 參數(shù)為指向保存配置信息結(jié)構(gòu)的指針
            // 返回值為成功標(biāo)志,true 代表成功,false 代表失敗
            bool read_cfg(CFG_DATA* p_data)
            {
               const string path_name = path+name;
               FILE* fp = fopen(path_name.c_str(), "r");
               if( fp == NULL )
                   return false;

               // 使用 fp 讀取配置文件,放入 CFG_DATA 結(jié)構(gòu)
               ... ...
               ... ...

               return true;
            }

            ... ....

            “在我這里運(yùn)行的好好的,但提交給測(cè)試組做單元測(cè)試的時(shí)候卻總是出毛病,說(shuō)是找不到配置文件,我去他們那里看過(guò)了,配置文件的名字和路徑都是對(duì)的呀,真是太奇怪了。”

            zero 斜著眼看了看這段代碼,對(duì)其中的風(fēng)格大為不滿(mǎn):“我說(shuō) pisces,錯(cuò)誤先不提,你這段代碼的風(fēng)格實(shí)在不太象 C++ 啊。首先參數(shù)應(yīng)該用引用,它的安全性可比指針高多了,而且你既然用了指針,就應(yīng)該用斷言做檢查么;其次你干嗎不用流來(lái)讀取文件呢?非要用 fopen ……”

            “我知道我知道!” pisces 忙不迭的打斷了 zero,“我知道這里我的風(fēng)格不太好,可是無(wú)論怎樣這段打開(kāi)文件的代碼應(yīng)該沒(méi)錯(cuò)呀?可現(xiàn)在問(wèn)題是打開(kāi)文件的時(shí)候出錯(cuò),明明文件在那兒的,可函數(shù)總是返回 false 。幫我先把這個(gè) bug 找出來(lái)嗎,幫幫忙了 ~~~~~ ”

            “好好!”,zero 搖了搖頭,開(kāi)始尋找錯(cuò)誤。5 分鐘過(guò)去,zero 的眉頭漸漸皺了起來(lái),這段只有三五行的代碼看起來(lái)一目了然,根本沒(méi)有隱藏錯(cuò)誤的地方。zero 把這段代碼引進(jìn)他用來(lái)測(cè)試的工程里,編譯連接,測(cè)試運(yùn)行,程序一切正常,正確的找到了配置文件。這是怎么回事?zero 迷惑了。

            “zero?” pisces 將探詢(xún)的眼光投向 zero。“呃 …… 別急,我們?nèi)y(cè)試組那里看看究竟怎么回事。” zero 心存僥幸,沒(méi)準(zhǔn)是測(cè)試組弄錯(cuò)了呢?10 分鐘之后,zero 垂頭喪氣的回來(lái)了,后面跟著 pisces。測(cè)試組沒(méi)有弄錯(cuò),在他們那里這段代碼確實(shí)不能正常工作,調(diào)試器顯示,作為文件名傳入 fopen 的是個(gè)空字符串。這是怎么回事?zero 一邊想著,一邊往自己的座位走去 ———— 哎?那個(gè)站在自己計(jì)算機(jī)前的人不是 …… 不是 …… Solmyr 么?他手上拿的是 ……

            zero 本能的感到了危險(xiǎn),猛的一偏頭!一個(gè)文件夾從離他的臉只有 0.01 公分的地方唰的一下擦了過(guò)去!可惜后面的 pisces 就沒(méi)有這么幸運(yùn)了,被打個(gè)正著!

            Solmyr 看了一眼正捂著臉的 pisces,對(duì)嚇出一身冷汗的 zero 問(wèn)道:“屏幕上那段代碼不是你寫(xiě)的吧?”

            “對(duì),是她寫(xiě)的。” zero 同情的看了看 pisces ,后者好象還沒(méi)有從打擊中恢復(fù)過(guò)來(lái) ……

            “有因就有果,真是一點(diǎn)也不會(huì)錯(cuò)啊 ……” Solmyr 聳聳肩,“知道這段代碼為什么會(huì)出錯(cuò)么?”

            zero 苦笑:“不知道。”

            “把眼光放開(kāi)一點(diǎn),你看一下調(diào)用這個(gè)函數(shù)的地方就知道了。”

            zero 調(diào)出了整個(gè)工程。按照文檔上的說(shuō)明,read_cfg 是整個(gè)系統(tǒng)初始化過(guò)程的步驟之一,當(dāng)系統(tǒng)啟動(dòng)時(shí)會(huì)讀取配置文件確定一些初始化的參數(shù)。據(jù)此,zero 很容易的找到了調(diào)用處,在另外一個(gè) cpp 文件中:

            #include "config.h"    // 其中聲明了 read_cfg 這個(gè)函數(shù)

            class system
            {
            public:
               // 完成系統(tǒng)啟動(dòng)時(shí)的初始化工作
               system()
               {
                   CFG_DATA data;
                   read_cfg(&data);

                   // 使用 data 中的信息配置系統(tǒng)
                   ... ...
               }

               // 完成系統(tǒng)退出時(shí)的清理工作
               ~system()
               {
                   ... ...
               }

               ... ...
            };

            system theSystem;    // 代表整個(gè)系統(tǒng)的全局對(duì)象

            Solmyr 清了清嗓子:“這是個(gè)看起來(lái)很干凈的手法。system 這個(gè)類(lèi)只有這里一個(gè)全局對(duì)象,這個(gè)全局對(duì)象代表了整個(gè)系統(tǒng),它構(gòu)造,系統(tǒng)做初始化工作;它析構(gòu),系統(tǒng)開(kāi)始做退出時(shí)的清理工作。全局對(duì)象的身份保證了它會(huì)在 進(jìn)入 main 函數(shù)之前構(gòu)造,在 main 函數(shù)退出之后析構(gòu)。這一招是你教 pisces 的吧?”Solmyr 看了看 zero 。

            zero 點(diǎn)點(diǎn)頭:“沒(méi)錯(cuò),上次她問(wèn)我如何能夠比較好的處理初始化和清理的代碼,我想起了上次關(guān)于‘成對(duì)出現(xiàn) ’的討論(注一),就給她出了這個(gè)主意。”

            “思路是對(duì)頭的,但是實(shí)現(xiàn)的方式不妥,毛病就出在全局對(duì)象上面。我問(wèn)你,一個(gè) cpp 文件,或者說(shuō)得正式一點(diǎn),一個(gè)編譯單元中的全局對(duì)象構(gòu)造析構(gòu)的順序是怎樣的?”

            “ …… 應(yīng)該是按照定義它們的順序。” zero 努力的回憶一陣,很肯定的說(shuō)道。

            “正確,那么不同編譯單元之間全局對(duì)象的構(gòu)造順序呢?”

            “ …… 好象沒(méi)有明確的規(guī)則,這個(gè)應(yīng)該屬于標(biāo)準(zhǔn)未定義對(duì)吧?”

            “正確,所以 ……”

            “所 以 …… …… 啊!我明白了!哎呀!我怎么這么遲鈍!看到 fopen 傳入的是空字符串的時(shí)候我就應(yīng)該想到的!” zero 露出了恍然大悟的表情,“在打開(kāi)配置文件的代碼段中,保存文件名的 path 和 name 也是全局對(duì)象,換句話(huà)說(shuō),這兩個(gè) string 對(duì)象和 theSystem 對(duì)象的構(gòu)造次序是無(wú)法確定的。在測(cè)試組那里,theSystem 先于 path 和 name 構(gòu)造,所以當(dāng) theSystem 的構(gòu)造函數(shù)調(diào)用 read_cfg 函數(shù)的時(shí)候,path 和 name 這兩個(gè) string 對(duì)象根本還沒(méi)有來(lái)得及構(gòu)造!當(dāng)然無(wú)法取出文件名和路徑來(lái)!而在我和 pisces 的計(jì)算機(jī)上,構(gòu)造次序與之相反,這段代碼就可以正確運(yùn)行。”

            “很好,那么如何解決呢?”

            “嗯 …… …… 我想只要盡可能避開(kāi)全局對(duì)象就行了,一方面 theSystem 這個(gè)對(duì)象可以放到 main 函數(shù)里,一樣可以保證正確完成初始化工作和清理工作;另一方面,read_cfg 那邊最好也不要用全局的 string 對(duì)象了,一樣可以用局部對(duì)象。這樣是能夠解決這個(gè)問(wèn)題 ……” zero 皺起了眉頭,顯然對(duì)這個(gè)解法還不太滿(mǎn)意,“那如果我有一些全局性質(zhì)的對(duì)象,而且希望精確的定義它們的構(gòu)造次序,該怎么辦呢?”

            Solmyr 點(diǎn)了點(diǎn)頭:“沒(méi)錯(cuò),有時(shí)候這確實(shí)是個(gè)合理的要求。對(duì)此最簡(jiǎn)單的解法是‘被函數(shù)包裝的 static 對(duì)象’(注二),象這樣:”

            system& theSystem()
            {
               static system instance;
               return instance;
            }

            “instance 是個(gè) static 對(duì)象,這保證了它的生存期,然后它會(huì)在第一次調(diào)用這個(gè)函數(shù)的時(shí)候構(gòu)造。針對(duì)你的問(wèn)題,只要你聲明多個(gè)這樣的函數(shù),然后保證它們第一次調(diào)用的次序,就可以保證這些對(duì)象構(gòu)造的次序了。”

            zero 若有所思的點(diǎn)了點(diǎn)頭。

            “說(shuō) 起來(lái),次序問(wèn)題絕對(duì)不只這一個(gè),C++ 中類(lèi)似的問(wèn)題相當(dāng)多。和這個(gè)問(wèn)題最接近的,是類(lèi)的成員和基類(lèi)的構(gòu)造次序,其他的還有表達(dá)式求值的次序、函數(shù)參數(shù)求值的次序,(注三)等等。遇到次序問(wèn)題, 千萬(wàn)不要想當(dāng)然,問(wèn)自己一句:這個(gè)次序有定義嗎?有定義的要遵守,無(wú)定義的要避開(kāi)。好了,這個(gè)問(wèn)題大概就是這樣,接下來(lái)你的任務(wù)是 …… ”

            “我知道,把這些討論整理成文檔對(duì)吧?”

            “不,是想辦法讓 pisces 搞懂這個(gè)問(wèn)題。”

            “…… …… …… …… …… ……”

            望著 Solmyr 甩手匆匆離去的背影,再看看身邊正用最拿手的“誠(chéng)懇”眼神看著自己的 pisces ,zero 突然泛起了一種奇怪的感覺(jué):好象以前只是單純被 Solmyr 砸的日子也沒(méi)有那么糟糕 …… …… ……

            posted on 2009-08-19 12:03 李現(xiàn)民 閱讀(459) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): 絕對(duì)盜版

            99久久er这里只有精品18| 久久99国产一区二区三区| 久久久精品2019免费观看| 久久人人爽人人人人爽AV | 国产精品99久久免费观看| yellow中文字幕久久网| 久久人做人爽一区二区三区| 国产精品久久久久影院色| 久久久免费观成人影院| 国产精品99久久免费观看| 久久精品国产亚洲Aⅴ香蕉 | 久久精品人人做人人爽电影| 久久99精品久久久久久hb无码| 亚洲欧美日韩精品久久亚洲区| 99久久精品毛片免费播放| 久久久久高潮综合影院| 日韩中文久久| 国产成人无码精品久久久性色| 国产亚洲综合久久系列| 欧美成人免费观看久久| 无码人妻久久一区二区三区蜜桃| 精品久久一区二区三区| 99久久精品免费| 久久狠狠一本精品综合网| 欧美久久一级内射wwwwww.| 国产69精品久久久久9999| 精品国产乱码久久久久久1区2区 | 国内精品免费久久影院| 欧美熟妇另类久久久久久不卡 | 99久久婷婷国产综合亚洲| 久久天天躁狠狠躁夜夜2020老熟妇 | 久久精品国产精品亚洲| 久久亚洲精品成人无码网站| 久久国产精品成人免费| 久久久久久亚洲精品成人| 亚洲精品无码久久久久去q| 精品国产乱码久久久久软件| 要久久爱在线免费观看| 欧美午夜A∨大片久久| 久久99精品久久久久久齐齐| 久久久精品无码专区不卡|