2018/12/19

[c/c++]snprintfくらいしかあふれても\0付加してくれない

忘却とは忘れ去ることなり・・・。

文字列あふれなんか上位層でカットして、下位層はそのままスルーして使ってしまえ!と実装していたのだが、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 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。