<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 內存空間的有名與無名 現在來看兩行 C 代碼: ~~~ int foo = 10; int *bar = &foo; ~~~ `foo`?是什么?`foo`?表示一個內存地址。`foo`?前面的?`int`?是數據類型修飾,它表示?`foo`?是內存中 4 個連續字節的首字節地址( 64 位機器上,`int`?類型的數據長度為 4 個字節)。C 編譯器總是會根據某個內存地址相應的類型來確定以該內存地址起始的一段連續字節中所存儲的數據的邏輯意義。因此,當我們用?`int`?類型來修飾?`foo`,編譯器就會認為以?`foo`?開始的連續 4 個字節中存儲的數據是一個整型數據。在上述代碼中,這個整型數據是?`10`,我們通過賦值運算符?`=`?將這個整型數保存到內存中以?`foo`?地址開始的連續 4 個字節中。 從此刻開始,要記住一個事實,那就是?C 語言中所有的變量名,本質上都是內存地址。之所以不直接使用內存地址,而是使用一些有意義的名字,這就類似于沒人愿意用你的身份證號來稱呼你,大家更愿意用你的姓名來稱呼你。 由于 C 語言認為數據的長度是由其類型確定的。例如,`int`?類型的數據長度是 4 個字節,`char`?類型的數據長度是是 1 個字節,用戶自定義的?`struct`?類型的數據長度則是根據實際情況而待定。在這種情況下,所有表示內存地址的名字,它們實質上表示的是內存中各種類型數據存儲空間的起始地址——專業一點,就是基地址。凡是用名字來表示基地址的內存空間,我們就將其稱為有名的內存空間。 再來看?`bar`?是什么?`bar`?是內存地址的名字,由于?`bar`?前面有個?`*`?號,這表示我們打算在以 bar 為基地址的連續 8 個字節中存儲一個內存地址(別忘了,我們是在 64 位機器上,指針數據的長度是 8 個字節)——`foo`?所表示的那個地址,亦即?`&foo`。在這里,?`&`?是取值符,它會對?`foo`?說,你甭給我耍花樣了,老實交代你的身份證號!在`*`?之前還有?`int`,這意味著在以 bar 為基地址的連續 8 個字節中存儲的那個內存地址是某個用于存儲整型數據的內存空間的基地址。 由于?`bar`?是某個內存空間的基地址,而這個內存空間中存儲的是一個內存地址,所以?`bar`?就是所謂的指針。在這里,我們可以認為?`bar`?是對某塊以?`foo`?為基地址的內存空間的『引用』,也就是在一個房間號為?`bar`?的房間里存儲了房間號`foo`。按照 C 語言教材里常用的說法,可將?`int *bar = &foo`?這件事描述為『指針?`bar`?指向了整型變量?`foo`』,然而事實上內存里哪有什么針,哪有什么指向?一切都是內存空間的引用。在上面的例子里,我們是用?`foo`?來直接引用某個內存空間,然后又使用?`bar`?來間接引用某個內存空間。 在上面的例子里,`bar`?引用的是一個有名的內存空間。那么有沒有無名的內存空間呢?看下面的代碼: ~~~ int *bar = malloc(sizeof(int)); ~~~ `malloc(sizeof(int))`?就是一個無名的內存空間,因為它是一個表達式,而這個表達式描述的是一系列行為,行為需要借助動詞來描述,而無法用名詞來描述。比如『我在寫文章』,這種行為無法只使用名詞來描述,必須借助動詞。任何會終止的行為都可表示為一系列的狀態的變化,也就是說任何會終止的行為都會產生一個結果,而這個結果可以用名詞來描述。例如?`malloc(sizeof(int))`?這個行為就是可終止的,它的結果是它在內存所開辟 4 個字節的空間的基地址,這個基地址是沒有名字的,所以它就是個無名的基地址,因此它對應的內存空間就是無名的內存空間,但是如果我們想訪問這個空間,就必須為它取個名字,當我們用?`bar`?指針引用它的基地址時,它就變成有名的了。 C 語言的創始人—— Dennis Ritchie 與 Brian Kernighan 將帶名字的存儲空間稱為對象(Object)——并非『面向對象編程』中的對象,然后將指代這個對象的表達式稱為左值(lvalue)。也就是說,在 C 語言中,上例中的?`foo`?與?`bar`?都是左值,因為它們總是能夠出現在賦值符號的左側。 看下面的代碼: ~~~ int foo = 10; int *bar = &foo; printf("%d", *bar); ~~~ 第三行的?`printf`?語句中的?`*bar`?也是一個左值,因為它指代了一個有名字的存儲空間,這個存儲空間的名字就叫做`*bar`。這個存儲空間其實就是以?`foo`?為基地址的存儲空間。在表達式?`*bar`?中,?`*`?號的作用是解引用,就是將以?`bar`為基地址的內存空間中存儲的內存地址取出來,然后去訪問這個內存地址對應的內存空間。由于?`*bar`?的類型是?`int`,所以程序自身就可以知道要訪問的是以?`*bar`?為基地址的 4 個字節,因此它可以準確無誤的將整型數據?`10`?取出來并交給`printf`?來顯示。 指針最黑暗之處在于,當你拿到了一塊內存空間的基地址之后,你可以借助這個基地址隨意訪問內存中的任何區域!也就是說,你可以從通過指針獲得內存空間的入口,然后你可以讓你的程序在內存中(棧空間)隨便逛,隨便破壞,然后你的程序可能就崩潰了。你的程序如果隱含緩沖區溢出漏洞,它甚至可被其他程序控制著去執行一些對你的系統非常不利的代碼,這就是所謂的緩沖區溢出攻擊。C 語言不提供任何緩沖區保護機制,能否有效保護緩沖區,主要取決于你的 C 編程技藝。 > 現在我們寫 C 程序時,基本上不需要擔心自己的程序會遭遇緩沖區溢出攻擊。因為只有那些被廣泛使用的 C 程序才有這種風險;如果很不幸,你寫的 C 程序真的被很多人使用了,那也不需要太擔心。《深入理解計算機系統》在 3.12 節『存儲器的越界引用和緩沖區溢出』中告訴我們,現代操作系統對程序運行時所需要的棧空間是隨機生成的,導致攻擊者很難獲得棧空間中的某個確定地址,至少在 Linux 系統中是這樣子。C 語言編譯器提供了棧破壞檢測——至少在 GCC 中是這樣,其原理就是程序的棧空間放置了一只『金絲雀』,程序在運行中一旦發現有襲擊『金絲雀』的可恥代碼,它就會異常終止。處理器層面也對可執行代碼所在的內存區域進行了限定,這樣攻擊者很難再向程序的棧空間插入攻擊系統的可執行代碼了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看