scanfのデメリット
2023-08-31 02:14:30
疑問点
のデメリットを知りたいのですが。
scanf()
.
多くのサイトでは
scanf
を使用すると、バッファオーバーフローが発生する可能性があると書かれています。この理由は何でしょうか?他に
scanf
?
どのように解決するのですか?
scanfの問題点は、(最低でも)以下の通りです。
-
を使って
%s
を使用してユーザーから文字列を取得するため、文字列がバッファより長くなる可能性があり、オーバーフローを引き起こします。 - スキャンに失敗すると、ファイル ポインタが不確定な場所に残る可能性があります。
私は非常に好んで
fgets
を使用して行全体を読み込む方が、読み込むデータ量を制限することができます。もし、1K のバッファがあり、そこに
fgets
で読み込んだ場合、その行が長すぎるかどうかは、行末に改行文字がないことで判断できます (改行のないファイルの最終行はともかくとして)。
それから、ユーザーに文句を言うか、残りの行にもっとスペースを割り当てることができます (必要であれば、十分なスペースができるまで継続的に)。どちらの場合でも、バッファオーバーフローのリスクはありません。
一旦行を読み込んだら、あなたは
を知ることができます。
で、次の行の位置がわかるので、問題はありません。次に、あなたは
sscanf
という文字列を作成することができます。
これは、私が頻繁に使用するコードのスニペットで、ユーザーに情報を求めるときにバッファオーバーフローが発生しないことを保証します。
必要であれば、標準入力以外のファイルを使用するように簡単に調整できます。また、呼び出し元に返す前に、それ自身のバッファを割り当てさせることもできます (そして、十分に大きくなるまで増やし続けます) (もちろん、呼び出し元はそれを解放する責任があります)。
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
#define SMALL_BUFF 3
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Size zero or one cannot store enough, so don't even
// try - we need space for at least newline and terminator.
if (sz < 2)
return SMALL_BUFF;
// Output prompt.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
// Get line with buffer overrun protection.
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// Catch possibility of `\0` in the input stream.
size_t len = strlen(buff);
if (len < 1)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[len - 1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[len - 1] = '\0';
return OK;
}
そして、そのためのテストドライバ。
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
最後に、動作を確認するためのテスト実行です。
$ printf "\0" | ./tstprg # Singular NUL in input stream.
Enter string>
No input
$ ./tstprg < /dev/null # EOF in input stream.
Enter string>
No input
$ ./tstprg # A one-character string.
Enter string> a
OK [a]
$ ./tstprg # Longer string but still able to fit.
Enter string> hello
OK [hello]
$ ./tstprg # Too long for buffer.
Enter string> hello there
Input too long [hello the]
$ ./tstprg # Test limit of buffer.
Enter string> 123456789
OK [123456789]
$ ./tstprg # Test just over limit.
Enter string> 1234567890
Input too long [123456789]
関連
-
[C] Error [Error] 代入の左オペランドとして lvalue が必要です。
-
[解決済み] printf ファミリーを使用して、size_t 変数をポータブルに印刷するにはどうすればよいですか?
-
C++の配列コピー
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] 配列のすべてのメンバーを同じ値で初期化するには?
-
[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
-
[解決済み] 講師が書いたC言語のファイルは、なぜ最初の行に#が一つ付いているのですか?
-
[解決済み】高放射能環境下で使用するアプリケーションのコンパイルについて
-
[解決済み】cでscanfを使用してdouble値を読み込む
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
赤線の位置は必ずしも間違っていない:式は変更可能なlvalueでなければならないエラーは、この文とは別の場所に存在する可能性があります。
-
[C] Error [Error] 代入の左オペランドとして lvalue が必要です。
-
[解決済み] エラー C4996: 'scanf' です。この関数または変数は、C言語プログラミングでは安全でない可能性があります。
-
[解決済み] flexible array member not at end of structエラーの原因は何ですか?
-
[解決済み] C - Setデータ構造を実装するには?
-
[解決済み] mallocの結果はキャストするのですか?
-
[解決済み] C言語のコードで「:-!」とは何ですか?
-
[解決済み] C言語でのブーリアン値の使用
-
[解決済み] printfは、フォーマット文字列の中に改行がないと、呼び出し後にフラッシュしないのはなぜですか?
-
[解決済み] FortranはC言語よりも重い計算を最適化しやすいですか?