<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-144  評論-80  文章-1  trackbacks-0

    一次偶然的情況下我發現以下代碼竟然無法被編譯通過(如果你的編譯器,比如VC6或VC2003,允許它編譯通過,我想你首先應該換個編譯器,比如GCC或VC2005):
    void foo( const char* [] ) { }
    int main( void )
    {
        char* s[2];
        foo( s );
    }

    簡化成更一般的形式是:
    char** p1 = 0;
    const char** p2 = p1;

    錯誤是:invalid conversion from `char**' to `const char**'.

    lostpencil更加仔細,使用C編譯器給出的是一個警告:
    initialization from incompatible pointer type.

    隨后hpho給出了合理的解釋,同時comp.lang.c++.moderated上的Ulrich Eckhardt也用代碼進行了說明。

    用代碼來說明最直觀了:
    const char* s = "abc";
    int main( void )
    {
        char* p0 = 0;
        char** p1 = &p0;
        const char** p2 = p1;
    // 先假設這一句是合法的 ( 測試時,可以先強制類型轉化一下 )
        *p2 = s;
        *p0 = 'A';
    // 通過p0在修改不應該被修改的s,這顯然和const相違背,其運行結果不可知。
    }




    看了 **的 想到的
    tekyDec 29, 2005 -  Show original item

    看完后.明白**講的為什么char** 不能自動轉化為 const char**,(原文)但對我影響最深的是下面的話:

    ==================================================================
    char *p="abc" 能不能編譯通過要看你使用的編譯器。鑒于大量遺留代碼的存在,大部分編譯器允許其通過,或者給個警告。當然,程序員自己必須保證絕不去修改其值。

    程序員不應該在代碼中出現*p='A'這樣的語句。這是當初約定好了的:編譯器允許char *p="abc"通過,而程序員保證不去修改它。
    b. *p='A'編譯時應該允許通過,因為單就這條語句而言,它完全合法。
    c. 運行時*p='A'能不能通過要看實際的運行環境,包括你使用的操作系統、編譯器、編譯器選項 等等,一句話,其運行結果由不得你,且不應該由你去關心,因為這種行為本身已經違反約定了。
    ==================================================================

    工作關系吧,用CString 和string用的太多了,很少這樣定義字符串 char *p=“abcde“了
    匝一看,還不適應,:(,漸漸的回想才想起一些來(哎,還是太生疏,趕快寫下來,以后別忘了)

    這樣定義的字符串char *p=“abcde“ ; char *p1=“123445667“;

    正如上面提到的是不能再 *p='A',運行的時候會出錯,同樣,strcpy(p,p1)也會出錯喲,

    "abcde"字符串可以看做是個常量字符串了,是不能被修改的,

    但如果 char p[]=“abcde“ 這樣定義,就沒有問題,你可以修改*p='A',只要不越界就ok.

    并且發現這樣兩種定義
    char *p=“abcde“

    char p[]=“abcde“

    在運行的時候,p指向的地址也不是一樣的,可見char *p=“abcde“還是有特殊的處理 :),具體怎么處理就不知道了,高手請指教:)


    隨著測試,又發現個問題,可能是個老問題了吧:


    int main(int argc, char* argv[])
    {
     int t[10];
     char p1[7]="123456";
     const char *p2="1234567890123213123";
     
     int len(0);
     
      //*p1='C';  err

     len=strlen(p1);
     printf("%d\n",len);
     
     strcpy(p1,p2);   ///??????????
     
     printf("%s\n",p1);
     
     len=strlen(p1);
     
     printf("%d\n",len);
     return 0;
    }

    我定義的是7個字符數組, 但用strcpy把p2拷到p1中,p1是放不下的,但程序卻正常執行,warning ,err都沒有,運行也正常?


    輸出

    6
    1234567890123213123
    19

    應該是使用內存越界了阿??怎么會正常運行呢?

    難道對于內存越界的使用,運氣好才崩潰表現出來,運氣不好就正常運行??


     

    posted on 2005-12-29 23:00 小力力力 閱讀(3900) 評論(1)  編輯  收藏 所屬分類: C/C++

    評論:
    # re: 為什么 char** 不能自動轉化為 const char** (轉) 2006-06-04 15:24 | Damnation
    對于你的最后一個問題,也就是所謂的Buffer Overrun,由于老舊的strcpy的不安全性,使得內存(字符串)拷貝越界。

    但是結果會如何則取決于當時棧框架(Stack Frame)的情況,如果越界到儲存返回地址的話,則極有可能會崩潰,運氣好(也可以說是差)的話,則會跳到某未知指令,然后繼續執行……(程序員最大的災難)黑客也可以通過這種手段來改變程序的流程。VC2005好像可以開啟對Buffer Overrun的檢測,原理就是在存返回地址的位置前放置一個防護碼,每次執行RET指令前先檢查一下防護碼的正確性,如果不正確,則說明IP已經被重寫了。

    至于為什么上面的程序可以正常運行,是因為在p1前面的int t[10]起到了緩沖作用,strcpy把部分內存越界拷貝到了那數組里(記住數值是由高位到地位進棧,所以數組的地址比字符串高),沒有抹掉返回地址,所以程序可以正常運行。

    不過從VC2005開始,編譯器已經禁止使用大部分的strxxx之類的函數了,而鼓勵程序員使用strxxx_s之類的安全函數。  回復  更多評論
      
    主站蜘蛛池模板: 国产亚洲精品第一综合| 亚洲人成色99999在线观看| EEUSS影院WWW在线观看免费| 男女啪啪永久免费观看网站| 亚洲日韩乱码中文字幕| 无码高潮少妇毛多水多水免费| 亚洲国产福利精品一区二区| 精品国产sm捆绑最大网免费站 | a级毛片免费在线观看| 亚洲午夜日韩高清一区| 亚欧国产一级在线免费| 国产亚洲无线码一区二区| 无码一区二区三区免费| 亚洲精品国产啊女成拍色拍| 永久免费av无码不卡在线观看| 亚洲熟妇无码AV| 免费在线不卡视频| a级日本高清免费看| 久久亚洲美女精品国产精品 | 久久久久久AV无码免费网站下载| 亚洲成人精品久久| 国产在线观看片a免费观看| 亚洲男人的天堂网站| 久久久久亚洲AV成人网| 免费在线中文日本| 亚洲精品亚洲人成在线播放| 在线看片无码永久免费aⅴ| 亚洲免费在线观看| 亚洲短视频在线观看| 日韩中文字幕免费| 成人免费一区二区三区| 亚洲精品中文字幕无乱码| 在线jyzzjyzz免费视频| 久青草视频97国内免费影视| 亚洲国产成人手机在线电影bd| 成人免费在线观看网站| 中文字幕乱码免费看电影| 色偷偷亚洲女人天堂观看欧| 国产精品亚洲综合一区| 18禁免费无码无遮挡不卡网站 | 亚洲第一精品电影网|