<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 練習36:更安全的字符串 > 原文:[Exercise 36: Safer Strings](http://c.learncodethehardway.org/book/ex36.html) > 譯者:[飛龍](https://github.com/wizardforcel) 我已經在練習26中,構建`devpkg`的時候介紹了[Better String](http://bstring.sourceforge.net/)庫。這個練習讓你從現在開始熟悉`bstring`庫,并且明白C風格字符串為什么十分糟糕。之后你需要修改`liblcthw`的代碼來使用`bstring`。 ## 為什么C風格字符串十分糟糕 當人們談論C的問題時,“字符串”的概念永遠是首要缺陷之一。你已經用過它們,并且我也談論過它們的種種缺陷,但是對為什么C字符串擁有缺陷,以及為什么一直是這樣沒有明確的解釋。我會試著現在做出解釋,部分原因是C風格字符串經過數十年的使用,有足夠的證據表明它們是個非常糟糕的東西。 對于給定的任何C風格字符串,都不可能驗證它是否有效。 + 以`'\0'`結尾的C字符串是有效的。 + 任何處理無效C字符串的循環都是無限的(或者造成緩沖區溢出)。 + C字符串沒有確定的長度,所以檢查它們的唯一方法就是遍歷它來觀察循環是否正確終止。 + 所以,不通過有限的循環就不可能驗證C字符串。 這個邏輯非常簡單。你不能編寫一個循環來驗證C字符串是否有效,因為無效的字符串導致循環永遠不會停止。就是這樣,唯一的解決方案就是包含大小。一旦你知道了大小,你可以避免無限循環問題。如果你觀察練習27中我向你展示的兩個函數: > 譯者注:檢驗C風格字符串是否有效等價于“停機問題”,這是一個非常著名的不可解問題。 ```c void copy(char to[], char from[]) { int i = 0; // while loop will not end if from isn't '\0' terminated while((to[i] = from[i]) != '\0') { ++i; } } int safercopy(int from_len, char *from, int to_len, char *to) { int i = 0; int max = from_len > to_len - 1 ? to_len - 1 : from_len; // to_len must have at least 1 byte if(from_len < 0 || to_len <= 0) return -1; for(i = 0; i < max; i++) { to[i] = from[i]; } to[to_len - 1] = '\0'; return i; } ``` 想象你想要向`copy`函數添加檢查來確保`from`字符串有效。你該怎么做呢?你編寫了一個循環來檢查字符串是否已`'\0'`結尾。哦,等一下,如果字符串不以`'\0'`結尾,那它怎么讓循環停下?不可能停下,所以無解。 無論你怎么做,你都不能在不知道字符串長度的情況下檢查C字符串的有效性,這里`safercopy`包含了程度。這個函數沒有相同的問題,因為他的循環一定會中止,即使你傳入了錯誤的大小,大小也是有限的。 > 譯者注:但是問題來了,對于一個C字符串,你怎么獲取其大小?你需要在這個函數之前調用`strlen`,又是一個無限循環問題。 于是,`bstring`庫所做的事情就是創建一個結構體,它總是包含字符串長度。由于這個長度對于`bstring`來說總是可訪問的,它上面的所有操作都會更安全。循環是有限的,內容也是有效的,并且這個主要的缺陷也不存在了。BString庫也帶有大量所需的字串操作,比如分割、格式化、搜索,并且大多數都會正確并安全地執行。 `bstring`中也可能有缺陷,但是經過這么長時間,可能性已經很低了。`glibc`中也有缺陷,所以你讓程序員怎么做才好呢? ## 使用 bstrlib 有很多改進后的字符串庫,但是我最喜歡`bstrlib`,因為它只有一個程序集,并且具有大多數所需的字符串功能。你已經在使用它了,所以這個練習中你需要從[Better String](http://bstring.sourceforge.net/)獲取兩個文件,`bstrlib.c`和`bstrlib.h`。 下面是我在`liblcthw`項目目錄里所做的事情: ```sh $ mkdir bstrlib $ cd bstrlib/ $ unzip ~/Downloads/bstrlib-05122010.zip Archive: /Users/zedshaw/Downloads/bstrlib-05122010.zip ... $ ls bsafe.c bstraux.c bstrlib.h bstrwrap.h license.txt test.cpp bsafe.h bstraux.h bstrlib.txt cpptest.cpp porting.txt testaux.c bstest.c bstrlib.c bstrwrap.cpp gpl.txt security.txt $ mv bstrlib.h bstrlib.c ../src/lcthw/ $ cd ../ $ rm -rf bstrlib # make the edits $ vim src/lcthw/bstrlib.c $ make clean all ... $ ``` 在第14行你可以看到,我編輯了`bstrlib.c`文件,來將它移動到新的位置,并且修復OSX上的bug。下面是差異: ```diff 25c25 < #include "bstrlib.h" --- > #include <lcthw/bstrlib.h> 2759c2759 < #ifdef __GNUC__ --- > #if defined(__GNUC__) && !defined(__APPLE__) ``` 我把包含修改為`<lcthw/bstrlib.h>`,然后修復2759行`ifdef`的問題。 ## 學習使用該庫 這個練習很短,只是讓你準備好剩余的練習,它們會用到這個庫。接下來兩個聯系中,我會使用`bstrlib.c`來創建Hashmap`數據結構。 你現在應該閱讀頭文件和實現,之后編寫`tests/bstr_tests.c`來測試下列函數,來熟悉這個庫: `bfromcstr` 從C風格字符串中創建一個`bstring`。 `blk2bstr` 與上面相同,但是可以提供緩沖區長度。 `bstrcpy` 復制`bstring`。 `bassign` 將一個`bstring`賦值為另一個。 `bassigncstr` 將`bsting`的內容設置為C字符串的內容。 `bassignblk` 將`bsting`的內容設置為C字符串的內容,但是可以提供長度。 `bdestroy` 銷毀`bstring`。 `bconcat` 在一個`bstring`末尾連接另一個。 `bstricmp` 比較兩個`bstring`,返回值與`strcmp`相同。 `biseq` 檢查兩個`bstring`是否相等。 `binstr` 判斷一個`bstring`是否被包含于另一個。 `bfindreplace` 在一個`bstring`中尋找另一個,并且將其替換為別的。 `bsplit` 將`bstring`分割為`bstrList`。 `bformat` 執行字符串格式化,十分便利。 `blength` 獲取`bstring`的長度。 `bdata` 獲取`bstring`的數據。 `bchar` 獲得`bstring`中的字符。 你的測試應該覆蓋到所有這些操作,以及你從頭文件中發現的更多有趣的東西。在`valgrind`下運行測試,確保內存使用正確。
                  <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>

                              哎呀哎呀视频在线观看