<li id="q4aaq"><object id="q4aaq"></object></li>
<xmp id="q4aaq">
  • <button id="q4aaq"><li id="q4aaq"></li></button>
  • <optgroup id="q4aaq"><sup id="q4aaq"></sup></optgroup><center id="q4aaq"><acronym id="q4aaq"></acronym></center>
  • <strong id="q4aaq"></strong>
  • <nav id="q4aaq"><menu id="q4aaq"></menu></nav>
    c程序設計
        最近程序發現了個奇葩現象,即從文件載入的證書鏈用openssl校驗是通過的,而用curl遠程獲取的就校驗失敗,錯誤碼7。而這些內容寫入文件在下一次程序啟動時載入校驗,又是成功的。

        排查了各種內存泄露、不可見字符的可能性后。突然想起來是不是libcurl靜態鏈接了openssl跟主程序動態鏈接的打架。查看后發現libcurl未靜態鏈接openssl。

         不過這也是一個啟示。想起來既然curl也用到了openssl,那么它在最后cleanup的時候會不會把全局的openssl數據結構給釋放掉。


         嘗試了一下,果然好了。原來我在一個函數里開頭調用curl_global_init,結尾調用curl_global_cleanup。這樣的話在程序結束時就會釋放openssl的全局數據結構。導致后續調用證書校驗報錯。

         不過openssl也不夠友好,報證書簽名錯誤,讓人很難聯想到是初始化問題。


          不過aes加密部分并不受這個影響。
        一直對內存操作的速度沒有數值概念,只泛泛的知道memset影響效率,反復分配釋放內存影響效率,具體速度如何,從來沒試過,今天試驗了一下。

        寫了個程序,分配一個指針數組,挨個分配內存,然后挨個釋放。使用的是一臺2核16g內存的虛擬機。gcc版本3.4.2

        先是分配了1w個100字節塊,發現5ms以內即可完成。
        然后擴大到500字節塊,速度沒什么變化。

        然后分配100w個字節塊,平均需要270ms左右。
        字節塊擴大的2k左右,大概5s完成。
        擴大到5k左右,大概12s左右。
        以上數據均為malloc+memset數據和calloc數據,兩者不相上下。

        只malloc不memset,大概能縮短20%左右,可見memset對速度還是有一定影響的,不過對于性能要求不是那么嚴苛的程序,設置一下提高程序穩定性也是值得的。避免某變量忘記初始化出現野值的問題。



    Tags:

    printf空指針NULL的問題

    [| 不指定 2012/05/16 17:52]
        今天發現程序中有幾個地方在沒有校驗指針為NULL的時候進行了打印日志操作,在字符串處理函數中使用NULL指針不是什么好事,研究了一下,發現在一些的linux發行版中,printf("%s",NULL)會打印一個“(NULL)”,而在solaris中則會出core,windows下也沒有問題。

        可見不同的c庫對于這個行為的實現不太一致。

        使用中還是要盡量避免這種用法,不過每次打日志前都要判斷指針情況確實比較惡。




        前兩天在用lua_next遍歷一個lua表的時候遇到了:PANIC: unprotected error in call to Lua API (invalid key to 'next')  仔細檢查了下代碼和堆棧信息,發現沒有問題,但為什么會說遍歷失敗呢?

        找到文檔看了下,原來lua_tolstring只支持number和string類型,但是對于number類型,在取值后也會轉換其在表中的實際內容為string,而我遍歷的表是使用默認自增索引作為key的,這樣對key調用這個函數會導致key變成字符串,因而遍歷有問題。

        如果表的key不一定是string,而又要用lua_tolstring獲取它的值,那么建議先在棧上復制一份,然后對于復制的值進行獲取。





    Tags:
        忘記之前從哪看過的一個文章說不要在for、while等循環內聲明變量,因為每次都會重復分配空間,很慢。

        今天發現一個模塊把變量聲明都放到while里面了,看了下代碼沒有發現必須聲明在里面的原因,于是開始懷疑是不是聲明在內外是差不多的。

        于是測試了一下:
    引用

    int main() {
        int i = 0;

        for(;i < 10000000; i++) {
            int b;
            b++;
        }

        return 1;
    }


    使用gcc 編譯,把int b放在循環內外試了試,用time ./a.out查看執行時間,發現用時基本相同。
    添加-O2優化選項,執行時間均縮減到之前的1/3,內外兩種方式時間依然相同。
    定義了一個struct實驗了下,結果相同
    也就是說棧上元素的操作不必糾結于變量聲明于何處。

    嘗試了下堆上元素操作,在預料之內:時間差距巨大,因為重復分配釋放內存。

    所以對于棧上元素,聲明放在循環里和循環外是一樣的。堆上元素不同,需注意。

    另,仍然需要注意一些計算操作需要放在循環外,比如求大小之類的,避免循環的每個周期重復計算。


    原因猜測:1, cpu對棧操作有優化,速度非常快。
    2,編譯器的基本優化中會優化(gcc沒有使用-O參數時仍會優化)
    具體原因待深究
        今天編譯lua程序時發現總是報缺少dlopen和pow之類的,需要手動加-lm -dl才行。感覺有點奇異,按我的理解來說使用靜態庫是不需要考慮依賴的。仔細研究了下,發現很多誤區。
        首先用靜態庫編譯出的可執行文件是不考慮庫依賴的,但并不代表用靜態庫時也不需要考慮。靜態庫在編譯時是不檢查函數是否被實現的,也就是說只需要.h即可。
        其次,靜態庫和動態庫其實區別很大,靜態庫只是編譯出.o的一個打包的文件,而動態庫添加了鏈接信息。

        這樣的話靜態庫還有一個特性,就是在靜態庫中可以調用一些預留接口,而把這些接口留待以后實現。
    Tags:
        今天程序出了一個core,是strcmp的時候有一個參數沒有判斷為NULL導致的,當我編寫了一個小程序:

    引用
    #include
    int main()
    {
    strcmp(NULL, "“);
    return 1;
    }

    測試的時候發現程序跑的毫無問題。
    編譯參數是gcc -g -O0,沒有開任何優化。

    gdb進去后發現strcmp根本沒有被執行,改成int a = strcmp(NULL, "");后,出core了。

    看來編譯器默認還是提供一定優化的。

    另外需要注意strcmp不會檢查參數(效率考慮),所以需要自己檢查。
        最近程序遇到一個小概率出core的bug,高壓力下大概10分鐘左右就會出core,gdb查看發現一個指針高四字節被置0xffffffff了,低四字節正常。
        該指針是局部變量,存放在棧上,排除了線程間同步互斥寫壞數據的可能。
        該指針前后變量均正常,都是指針,排除了寫越界的可能。

        通過日志查看,在返回該指針的函數返回前,指針正常,返回后高四字節即被置0xffffffff了。推斷應該是函數返回的過程中遭到了破壞。

        但不知道為什么返回的過程中會出錯,請教了下組內高工,高人就是高人,一聽問題描述就表示應該是函數聲明的問題。

        原來,在調用另一個so文件中的函數時,如果沒有該函數的聲明,由于從該so的符號表里可以找到函數,所以編譯可以通過,但gcc會把這個函數返回值按默認的int處理,這種情況下,32位機編譯的程序是沒問題的,但64位機上指針是8字節,導致高四字節數據丟失。但返回的指針超過int值域時,高四字節數據丟失,導致指針被破壞。

       所以函數聲明還是不可或缺的。
    Tags: ,
    分頁: 1/1 第一頁 1 最后頁 [ 顯示模式: 摘要 | 列表 ]
    色琪琪av男人的天堂-琪琪see色原网色原网站-天天谢天天谢天天要-欧美成人视频