愚かな法学C練習36:より安全な文字列
4859 ワード
練習36:より安全な文字列
原文:Exercise 36:Safer Strings
ドラゴン
既に練習26で
なぜCスタイルの文字列は非常に悪いのか
人々がCの問題について話すとき、「文字列」の概念は永遠に最も重要な欠陥の一つである.あなたはすでにそれらを使ったことがあり、私もそれらの様々な欠陥について話したことがありますが、なぜC文字列に欠陥があるのか、なぜずっとこのようにしているのかについて明確な説明がありません.私は今説明してみます.一部の原因はCスタイルの文字列が数十年の使用を経て、非常に悪いものであることを示す十分な証拠があります.
指定されたCスタイル文字列では、有効かどうかを検証することはできません.が 無効なC文字列を処理する任意のループは無限である(またはバッファオーバーフローをもたらす). C文字列には長さが指定されていないので、ループが正しく終了しているかどうかを確認する唯一の方法は、ループを巡回することです. であるため、限られたループを介さずにC文字列を検証することは不可能である.
この論理は非常に簡単だ.無効な文字列がループを停止させないため、C文字列が有効であるかどうかを検証するループを作成することはできません.このように、唯一の解決策はサイズを含むことです.大きさが分かれば、無限ループの問題を避けることができます.練習27で私があなたに示した2つの関数を観察すると、
Cスタイル文字列が「ダウンタイムの問題」に有効かどうかを確認することは、非常に有名な不可解な問題です.
どのようにしても、文字列の長さを知らずにC文字列の有効性をチェックすることはできません.ここでは
しかし、問題が発生しました.C文字列について、どのようにしてサイズを取得しますか.この関数の前に
そこで、
bstrlibの使用
改善された文字列ライブラリはたくさんありますが、
次は私が
14行目では、
このライブラリの使用を学習する
この練習は短いですが、残りの練習を用意させるだけで、このライブラリに使用されます.次の2つの連絡では、
ヘッダファイルと実装を読んで、
Cスタイル文字列から
上記と同じですが、バッファ長を指定できます.
コピー
1つの
1つの
2つの
2つの
1つの
1つの
文字列フォーマットを実行すると便利です.
あなたのテストは、これらの操作と、最初のファイルから発見されたもっと面白いものに上書きする必要があります.
原文:Exercise 36:Safer Strings
ドラゴン
既に練習26で
devpkg
を構築しているときにBetter Stringライブラリを紹介しています.この練習はあなたに今からbstring
ライブラリを熟知させ、Cスタイルの文字列がなぜ非常に悪いのかを理解させます.その後、liblcthw
のコードを変更してbstring
を使用する必要があります.なぜCスタイルの文字列は非常に悪いのか
人々がCの問題について話すとき、「文字列」の概念は永遠に最も重要な欠陥の一つである.あなたはすでにそれらを使ったことがあり、私もそれらの様々な欠陥について話したことがありますが、なぜC文字列に欠陥があるのか、なぜずっとこのようにしているのかについて明確な説明がありません.私は今説明してみます.一部の原因はCスタイルの文字列が数十年の使用を経て、非常に悪いものであることを示す十分な証拠があります.
指定されたCスタイル文字列では、有効かどうかを検証することはできません.
'\0'
で終わるC文字列が有効です.この論理は非常に簡単だ.無効な文字列がループを停止させないため、C文字列が有効であるかどうかを検証するループを作成することはできません.このように、唯一の解決策はサイズを含むことです.大きさが分かれば、無限ループの問題を避けることができます.練習27で私があなたに示した2つの関数を観察すると、
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
が一番好きです.プログラムセットが1つしかなく、必要な文字列機能がほとんどあるからです.すでに使用しているので、この練習ではBetter Stringから2つのファイル、bstrlib.c
とbstrlib.h
を取得する必要があります.次は私が
liblcthw
プロジェクトのカタログでやったことです.$ 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上のバグを修復したことがわかります.次の違いは、次のとおりです.25c25
< #include "bstrlib.h"
---
> #include
2759c2759
< #ifdef __GNUC__
---
> #if defined(__GNUC__) && !defined(__APPLE__)
に修正し、2759行ifdef
の問題を修正しました.このライブラリの使用を学習する
この練習は短いですが、残りの練習を用意させるだけで、このライブラリに使用されます.次の2つの連絡では、
bstrlib.c
を使用してHashmap`データ構造を作成します.ヘッダファイルと実装を読んで、
tests/bstr_tests.c
を作成して次の関数をテストして、このライブラリを熟知する必要があります.bfromcstr
Cスタイル文字列から
bstring
を作成します.blk2bstr
上記と同じですが、バッファ長を指定できます.
bstrcpy
コピー
bstring
.bassign
1つの
bstring
を別の値に割り当てます.bassigncstr
bsting
の内容をC文字列の内容に設定します.bassignblk
bsting
の内容をC文字列の内容に設定しますが、長さは指定できます.bdestroy
bstring
を破棄します.bconcat
1つの
bstring
の末尾にもう1つを接続します.bstricmp
2つの
bstring
を比較し、戻り値はstrcmp
と同じである.biseq
2つの
bstring
が等しいかどうかを確認します.binstr
1つの
bstring
が別のものに含まれているかどうかを判断する.bfindreplace
1つの
bstring
において別のものを探し、それを別のものに置き換える.bsplit
bstring
をbstrList
に分割する.bformat
文字列フォーマットを実行すると便利です.
blength
bstring
の長さを取得します.bdata
bstring
のデータを取得します.bchar
bstring
の文字を取得します.あなたのテストは、これらの操作と、最初のファイルから発見されたもっと面白いものに上書きする必要があります.
valgrind
でテストを実行し、メモリが正しく使用されていることを確認します.