C言語の設計ミスった危険な関数トップ10決めようぜ
最大のミスは、文字列そのものをデータ型としては持たずに、
文字列はヌルで終端された不定長の文字の配列であるとしたことにある。 C言語の関数名ってまだリンカがシンボルの先頭から6文字までしか認識しなかった頃の名残だしな
変な短縮形が多い strcpy()とか意図しようがしまいが簡単にメモリをぶっ壊せる
よくよく考えるとキチガイ過ぎる >>15
根本的な所を勘違いしてる。
C言語で安全性が求められないからと言って、
C言語で作ったアプリには安全性は求められるだろ?
例えば、getsは安全に使うことが不可能なんだよ。 >>18
> 例えば、getsは安全に使うことが不可能なんだよ。
ならgetsを使わずにgetcでやればいいだけ 組み込みでC言語は使うけど、10個以上の標準関数って使わないな...。 memcpy / memset / memcmp
strlen / str(n)cpy / str(n)cmp / str(n)cat
これで10個 組み込みで文字列扱わないことも多いね。
どんな製品でもほぼ使うのはmemset、memcpy、memcmpぐらいじゃない? >>25
>>1のリンク先より
未チェックの時代遅れの関数
以下の関数を、未チェックの時代遅れの関数と定義する。
memcpy, strcpy, strncpy, strcat, strncat (一部抜粋)
半分あてはまってるなw
>>26
memcpyは危険なので使うのはやめましょう memcpyが危険とか言うなら
C言語使うなってことになる >>28
標準じゃない関数だと...
失敗談みたいなのを期待してた? >>1
セキュリティ考慮していない元関数より、代替関数の設計ミスが酷いな
strtodとかなにこれw
エラーの返し方がアホすぎる >>32
> strtodとかなにこれw
> エラーの返し方がアホすぎる
そう言うのは改善案を提案しないと単なるアホの独り言にしかならんぞw 一体どういう考えで昔の人は、getsの仕様はあれでOKだと思ったんだろう?
どう考えてもバッファオーバーフローするやん?
しない方法なんて存在するの? バッファオーバーフローしないデータを食わせれば良い
わざわざ変なデータを入力するヤツが悪い
って考えの時代の関数だ gets は、もう、標準ライブラリにも入っていないので許せ >>36
1行80文字とかって決め打ちできる環境なんでしょ
自分しか使わないようなツールとかならこれで十分
って考え 8ビットの整数型を char などというものにしたのも、アメリカ人は
自分たちの英語しか知らない田舎者であることを如実に表している。 >>41
実に田舎者の考え方で笑える
逆だよ、都会の人間は都会のことしか知らないし知る必要がない
なぜか田舎の人間は都会のことも知ろうとするw > 逆だよ、都会の人間は都会のことしか知らないし知る必要がない
だから世界が狭くて無知になりやすい
> なぜか田舎の人間は都会のことも知ろうとするw
だから世界が広い C言語が出来た時の時代を考えれば十分
「変数名に日本語が使えない言語は糞」
って時代もそのうち来るよ >>44
残念ながらそうはなってないんだなw
狭く深くっていう世界だから
要するに田舎でな何をするにもオーバーヘッドが大きいってことな
今はネットでだいぶマシになったけどネット以前の情報収集考えたらアホでもわかる話 アホなデータ食わせるアホなやつのために堅牢な仕組みにする必要はない >>46
メモリが640kバイトしか使えなかった頃からのものだしな 大昔って端末やエディタなんかでも1行256とか1024バイト程度しか扱えなかったばず 昔は1行の長さを先に決めてファイルをクリエイトしました
途中で変更はできません 関数そのものじゃないが
breakにラベル指定出来なかったのは設計ミスやろ gotoはラベルのスコープが広いから使いにくい。ループごとに別のラベル名を
付けないといけないし、ラベル名を別のループ用のものと書き間違えると
意図しない所へ飛んで行ってしまう。スパゲッティでバグの元。
ループにラベルを付ければ、スコープがそのループ内に限定され、そのループの
外にある別のループに同じラベル名を付けることができるから、書きやすく
読みやすい。例えば、こんな感じ。
for @outer (i = 1; i <= 3; i++) {
for (j = 1; j <= 3; j++) {
printf("%d, %d\n", i, j);
if (i * j > 3) break @outer;
}
}
for @outer (i = 1; i <= 5; i++) {
for (j = 1; j <= 5; j++) {
printf("%d, %d\n", i, j);
if (i * j > 5) break @outer;
}
} 1000行のコードでbreak 7;とかされても、
どこに抜けるかわからんよな! ネストの数がわからないような巨大な構造は
それだけで最低だ
そんなんだと名前付きループにした所で
@outerなんて名前が使い回されて
同じ名前のループがネストされて
それこそ難読コードになる
それならユニークなラベルによるgotoの方が良い
>>57くらいのループなら
break 2;
は名前を考える手間が無くて楽だし
見にくくもない とは書いたけど
どっちも有るならどっちも欲しい
どっちかだけげならbreak 2;の方が欲しい
って感じ >>61
> そんなんだと名前付きループにした所で
> @outerなんて名前が使い回されて
> 同じ名前のループがネストされて
> それこそ難読コードになる
無能の妄想w ループの先頭、ループの終わり、break部分
3箇所見ないとダメってだけでダメな仕様 >>64
なぜか自分の前提は
> >>57くらいのループなら
なのにラベルにした途端にループの頭とbreakとループの終わりが一瞥でわからないとかアホすぎ 名前を付ける手間を許容するならgotoという解決法が既にある >>60
ネスト変わるような変更あるたびにbreakの引数勝手に書き換えてくれるエディタとかマクロが流行る >>67
ifとgotoあるからforもwhileもdoも要らんという主張か
本物のプログラマーだなw 歪んだ教育のせいで
gotoに拒絶反応を示す人が多いんだよな
2重ループを抜けるなら素直にgotoを使えって アセンブラの
jmp 1f
とかを C でやりたいという話なのか?
やってみりゃいいじゃん。プリプロセッサの出力を処理すればいい。
1 パスで出来ると思うよ。
ひょっとしてもう誰かがやってるかも。 for (i = 1; i <= 3; i++) {
for (j = 1; j <= 3; j++) {
printf("%d, %d\n", i, j);
if (i * j > 3) goto outer;
}
} outer:; for (i = 1; i <= 3; i++) {
for (j = 1; j <= 3; j++) {
printf("%d, %d\n", i, j);
if (i * j > 3) goto outer;
}
}
printf("complete\n");
outer:; わざわざ言語拡張しなくても
>>57以上の事が実現出来る ラベルのスコープを狭くしたいという話のようだから
マクロの中で使ってこそ真価を発揮するんじゃないかな。
フル仕様のパースが必要というわけではなく、かなり手抜きできそうではある。
あれば便利というのは否定しないが、C でそこまで必要かというと… {
goto hoge;
hoge:;
}
{
goto hoge;
hoge:;
}
これで二重になってたら困るしある意味なってなくても困るな マクロで二重以上のループってのもなかなか考えづらいなあ
一応、ラベル名をパラメータとする手もある
使う側のコストを考えるとgotoの為にパラメータを増やさないよな
gotoを使わない主義者がよくやってるように
余分な変数を使って実装するんだろうね アセンブラだとマクロローカルラベルってのがあったりする
ラベルを頻繁に使うので
あと
@@/@b/@fのように、
直近のラベルを指定する仕組みもある >>72 >>73 みたいなのって
gotoの使いどころだと思うんだけだ
gotoを使わない人はどう書いてるの?
特に >>57 の答えを聞いてみたい void print_data(void) {
for (i = 1; i <= 3; i++) {
for (j = 1; j <= 3; j++) {
printf("%d, %d\n", i, j);
if (i * j > 3) return;
}
}
}
print_data();
printf("complete\n"); void print_data(void) {
for (i = 1; i <= 3; i++) {
for (j = 1; j <= 3; j++) {
printf("%d, %d\n", i, j);
if (i * j > 3) return;
}
}
}
print_data();
outer より後に処理が続く場合
printf("complete\n"); "短い処理"をいちいち関数にしなくて済むから、break 2とかはあってもいいが、
長い処理は関数にしてないとろくにテストできないんだからgotoなんていらない gotoの基本的な使い方くらい知っておいた方が良いかと
ループを抜ける為だけに関数を分けないといけなくなるし
挙げ句の果てに言語の欠陥とか言い出す 今のC言語ではネストしたループから抜けるのはフラグを使うかgotoしかないからたいていgoto使ってるけどgotoなんて野蛮なものはできたら使いたくないから他の言語で実装されてるラベル付きbreakなりレベル付きbreakが欲しいって話だろ
今更gotoの基本的な使い方ガーとか言ってる奴はどんだけ低レベルなんだよw あれ?
returnで抜ける為に関数に分けるんじゃなかったの? gotoは野蛮とかいう歪んだ教育のせいで
わざわざ変数を定義したりわざわざ関数を分けたりして
わざわざ見にくいコードにしちゃう
生でポインタを扱う野蛮なC言語なんか使わないで
上品な言語を使った方が良いよ gotoじゃなくてgodowntoなら誰も文句言わなかった 自分は小規模な字句解析みたいなのでもgoto使うことがある。
ラベルで状態を表してgotoで遷移する。
goto使わなかったら状態を変数に入れて、
ループの中でswitchで場合分けするようなコードになって辛い。 ループの中のswitchでループを抜けるのに
gotoを使うんじゃ? 次の状態を返す関数ポインタでループすればいんじゃないの? >>87
returnで抜けるためというか、
1. gotoで抜けたい
2. 関数にするか
3. あ、そもそもコードが複雑なんだな
4. 関数にして正解だった
こんな感じかな。
gotoで抜けたいと思う=コードが複雑になってるという警鐘だと思ってる。 で>>82みたいな意味不明な関数の分け方をすると
>>57は、より複雑な記述をしたいっていう主張だし
gotoに親を殺された人の言うことは支離滅裂
理由が後付けだからそうなる > で>>82みたいな意味不明な関数の分け方をすると
なんで意味不明?
そもそもその処理に意味をもたせてから言おうよw
処理に意味をもたせると、関数にしたほうが良いと思うからさ > 理由が後付けだからそうなる
質問の方が先なのに、理由を先に言えるわけがないw
Q. 多重ループから抜けるのに、gotoは必要ですか?
A. 必要ありません。多重ループが必要になるぐらい複雑なら関数にしますから
これが普通だから、後付にはならないよね。 じゃあ>>57はどういうつもりで書いたんでしょうかね? 話を戻して
・ループを抜けた後に関数の後処理が必要な場合
・ループを抜けた後にローカル変数を使った処理をする場合
・他、意味的に関数内で処理したい場合
はどうするの? > ・ループを抜けた後に関数の後処理が必要な場合
前処理を関数の中でするな
> ・ループを抜けた後に関数の後処理が必要な場合
戻り値を返せ
>・他、意味的に関数内で処理したい場合
自分で具体例が思いつかないなら出すな