忘却とは忘れ去ることなり・・・。
文字列あふれなんか上位層でカットして、下位層はそのままスルーして使ってしまえ!と実装していたのだが、Linuxみたいにリソースが裕福な環境だと、チェックを減らしてROMやスタックの消費を抑えるよりも、きっちりチェックして安全を求めることが優先されるらしい。
ちっ。
以前調べた気もするが、記憶が無いので調べ直そう。
過去記事は、こちら。
[c/c++]strncatはあふれても\0付加しない
https://hiro99ma.blogspot.com/2016/12/ccstrncat0.html
どちらかといえば、snprintf()は\0を付加するが、それ以外はやってくれない、と覚えるのが良いのか。
でも、strncpy()なんかはメジャーな気がするから、やってくれるかもしれない(よくわからない期待)。
01: #include <stdio.h>
02: #include <string.h>
03:
04: #define STRMAX (10)
05:
06: int main(void)
07: {
08: char str1[STRMAX + 1];
09:
10: memset(str1, 'a', sizeof(str1));
11: snprintf(str1, sizeof(str1), "12345678901234567890");
12: printf("snprintf : [%s]\n", str1);
13:
14: memset(str1, 'a', sizeof(str1));
15: strncpy(str1, "12345678901234567890", sizeof(str1));
16: printf("strncpy : [%s]\n", str1);
17: }
snprintf : [1234567890]
strncpy : [12345678901]
一瞬、「おお、やってくれるやん」と思ったが、strncpy()では11文字出力されているので、STRMAX+1の後ろに\0がついていることになるな。
まあ、こういうのは、スタックの配置とアラインメントを考えて、こうするのがわかりやすかろう。
01: #include <stdio.h>
02: #include <string.h>
03:
04: #define STRMAX (15)
05:
06: int main(void)
07: {
08: char str0[STRMAX + 1];
09: char str1[STRMAX + 1];
10: char str2[STRMAX + 1];
11:
12: memset(str0, 'x', sizeof(str0));
13: memset(str2, 'y', sizeof(str2));
14:
15: memset(str1, 'a', sizeof(str1));
16: snprintf(str1, sizeof(str1), "12345678901234567890");
17: printf("snprintf : [%s]\n", str1);
18:
19: memset(str1, 'a', sizeof(str1));
20: strncpy(str1, "12345678901234567890", sizeof(str1));
21: printf("strncpy : [%s]\n", str1);
22: }
snprintf : [123456789012345]
strncpy : [1234567890123456yyyyyyyyyyyyyyyy`d�D�]
メモリの配置がどっち側かわからなかったので前後に追加したが、上から順番だったようだ。
strncpy()はstr1に20文字中16文字をコピーし、そのまま\0は付加しなかった。
メモリの境界としてつながっていたので、printf()するとstr2の"yyy..."が出力され、こちらも\0がなかったのでさらに後ろのゴミが出力されて、\0が現れたので止まった、というところだろう。
strncpy()も\0付加してくれていいような気がしたのだけど、余計なことはしないということで付加はしないのだろう。
snprintf()は、そもそもフォーマットという余計なことをするので、\0の付加くらいは当たり前という立場なのか。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。