2025
					11
					04
				
					2012
					06
					30
				
strncpyを使った安全な文字列コピー(C言語)
コピー元の文字列の長さが不明な時用のメモリ破壊を起こさない 文字列コピーの方法について、strncpyの動作を見ながら確認したメモ 結論から言うと strncpy(dst, src, DST_BUFF_LEN); dst[DST_BUFF_LEN-1] = '\0'; すれば破壊は起きない、ただsrcをコピーしきれないことがある。 下記のソースを試したコンパイラバージョンは gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)です。
ソースコード
/* nex2t_strncpy.c */
#include <stdio.h>
#include <string.h>
#define EX_STR "0123456789abcdefghij"
#define EX_STR2 "01234"
#define BUF_LEN     16
#define DEBUG_LINE "---------------------------------------------------------\n"
int main(void)
{
	int i;
	char buf[BUF_LEN];
	/* -------------------------------------------------------------- */
	printf(DEBUG_LINE);
	printf("use buffer buf[BUF_LEN] BUF_LEN=%d\n", BUF_LEN);
	printf(DEBUG_LINE);
	printf("EX_STR:%s [strlen(EX_STR):%ld, sizeof(EX_STR):%ld]\n", EX_STR,
	       strlen(EX_STR), sizeof(EX_STR));
	printf("       (over buf[BUF_LEN] size!!)\n");
	printf(DEBUG_LINE);
	printf("EX_STR2:%s [strlen(EX_STR2):%ld, sizeof(EX_STR2):%ld]\n",
	       EX_STR2, strlen(EX_STR2), sizeof(EX_STR2));
	printf("       (not over buf[BUF_LEN] size)\n");
	printf(DEBUG_LINE "\n");
	/* ---- Init after ----------------------------------------------- */
	printf("Init after\n");
	printf(DEBUG_LINE);
	for (i = 0; i < BUF_LEN; i++) {
		buf[i] = '\0';
	}
	for (i = 0; i < BUF_LEN; i++) {
		printf("buf[%d] = %d\n", i, buf[i]);
	}
	printf("buf[BUF_LEN] = %d  (secretly watch.)\n\n", buf[BUF_LEN]);
	/* ---- Normal_1 ------------------------------------------------ */
	printf("Normal_1\n");
	printf(DEBUG_LINE);
	strncpy(buf, EX_STR, 5);
	printf("strncpy(buf, EX_STR, 5);\n");
	printf("result:string:%s [strlen(buf):%ld, sizeof(buf):%ld]\n", buf,
	       strlen(buf), sizeof(buf));
	for (i = 0; i < BUF_LEN; i++) {
		printf("buf[%d] = %d\n", i, buf[i]);
	}
	printf("buf[BUF_LEN] = %d  (secretly watch.)\n\n", buf[BUF_LEN]);
	/* init */
	for (i = 0; i < BUF_LEN; i++) {
		buf[i] = '\0';
	}
	/* ---- Normal_2 ----------------------------------------------- */
	printf("Normal_2\n");
	printf(DEBUG_LINE);
	strncpy(buf, EX_STR, BUF_LEN);
	printf("strncpy(buf, EX_STR, BUF_LEN);\n");
	printf("result:string:%s [strlen(buf):%ld, sizeof(buf):%ld]\n", buf,
	       strlen(buf), sizeof(buf));
	for (i = 0; i < BUF_LEN; i++) {
		printf("buf[%d] = %d\n", i, buf[i]);
	}
	printf("buf[BUF_LEN] = %d  (secretly watch.)\n\n", buf[BUF_LEN]);
	printf("***Not write '\\0' automatically!! (buf[%d] = %d)\n",
	       BUF_LEN-1, buf[BUF_LEN-1]);
	printf("***Not write buf[BUF_LEN] (buf[%d] = %d)\n\n",
	       BUF_LEN, buf[BUF_LEN]);
	/* not init */
	/*
	for (i = 0; i < BUF_LEN; i++) {
		buf[i] = '\0';
	}
	*/
	/* ---- Normal_3 ----------------------------------------------- */
	printf("Normal_3\n");
	printf(DEBUG_LINE);
	strncpy(buf, EX_STR2, BUF_LEN);
	printf("strncpy(buf, EX_STR2, BUF_LEN);\n");
	printf("result:string:%s [strlen(buf):%ld, sizeof(buf):%ld]\n", buf,
	       strlen(buf), sizeof(buf));
	for (i = 0; i < BUF_LEN; i++) {
		printf("buf[%d] = %d\n", i, buf[i]);
	}
	printf("buf[BUF_LEN] = %d  (secretly watch.)\n\n", buf[BUF_LEN]);
	printf("***automatically write '\\0' to buf[15]\n");
	/* ---- Extra ------------------------------------------------- */
	printf("\nExtra\n");
	printf(DEBUG_LINE);
	strncpy(buf, EX_STR, 0);
	printf("strncpy(buf, EX_STR, 0);\n");
	printf("result:string:%s [strlen(buf):%ld, sizeof(buf):%ld]\n", buf,
	       strlen(buf), sizeof(buf));
	for (i = 0; i < BUF_LEN; i++) {
		printf("buf[%d] = %d\n", i, buf[i]);
	}
	printf("buf[BUF_LEN] = %d  (secretly watch.)\n\n", buf[BUF_LEN]);
	printf("Not write any.\n\n");
	/* ---- Right usage ------------------------------------------- */
	printf("Right usage\n");
	printf(DEBUG_LINE);
	strncpy(buf, EX_STR, BUF_LEN);
	buf[BUF_LEN-1] = '\0';
	for (i = 0; i < BUF_LEN; i++) {
		printf("buf[%d] = %d\n", i, buf[i]);
	}
	printf("buf[BUF_LEN] = %d  (secretly watch.)\n\n", buf[BUF_LEN]);
	printf("strncpy(buf, EX_STR, BUF_LEN); after buf[BUF_LEN-1] = '\\0';");
	return 0;
}
コンパイル例
gcc -W -Wall -o nex2t_strncpy nex2t_strncpy.c
実行結果
./strncpy
---------------------------------------------------------
use buffer buf[BUF_LEN] BUF_LEN=16
---------------------------------------------------------
EX_STR:0123456789abcdefghij [strlen(EX_STR):20, sizeof(EX_STR):21]
       (over buf[BUF_LEN] size!!)
---------------------------------------------------------
EX_STR2:01234 [strlen(EX_STR2):5, sizeof(EX_STR2):6]
       (not over buf[BUF_LEN] size)
---------------------------------------------------------
Init after
---------------------------------------------------------
buf[0] = 0
buf[1] = 0
buf[2] = 0
buf[3] = 0
buf[4] = 0
buf[5] = 0
buf[6] = 0
buf[7] = 0
buf[8] = 0
buf[9] = 0
buf[10] = 0
buf[11] = 0
buf[12] = 0
buf[13] = 0
buf[14] = 0
buf[15] = 0
buf[BUF_LEN] = 0  (secretly watch.)
Normal_1
---------------------------------------------------------
strncpy(buf, EX_STR, 5);
result:string:01234 [strlen(buf):5, sizeof(buf):16]
buf[0] = 48
buf[1] = 49
buf[2] = 50
buf[3] = 51
buf[4] = 52
buf[5] = 0
buf[6] = 0
buf[7] = 0
buf[8] = 0
buf[9] = 0
buf[10] = 0
buf[11] = 0
buf[12] = 0
buf[13] = 0
buf[14] = 0
buf[15] = 0
buf[BUF_LEN] = 0  (secretly watch.)
Normal_2
---------------------------------------------------------
strncpy(buf, EX_STR, BUF_LEN);
result:string:0123456789abcdef [strlen(buf):16, sizeof(buf):16]
buf[0] = 48
buf[1] = 49
buf[2] = 50
buf[3] = 51
buf[4] = 52
buf[5] = 53
buf[6] = 54
buf[7] = 55
buf[8] = 56
buf[9] = 57
buf[10] = 97
buf[11] = 98
buf[12] = 99
buf[13] = 100
buf[14] = 101
buf[15] = 102
buf[BUF_LEN] = 0  (secretly watch.)
***Not write '\0' automatically!! (buf[15] = 102)
***Not write buf[BUF_LEN] (buf[16] = 0)
Normal_3
---------------------------------------------------------
strncpy(buf, EX_STR2, BUF_LEN);
result:string:01234 [strlen(buf):5, sizeof(buf):16]
buf[0] = 48
buf[1] = 49
buf[2] = 50
buf[3] = 51
buf[4] = 52
buf[5] = 0
buf[6] = 0
buf[7] = 0
buf[8] = 0
buf[9] = 0
buf[10] = 0
buf[11] = 0
buf[12] = 0
buf[13] = 0
buf[14] = 0
buf[15] = 0
buf[BUF_LEN] = 0  (secretly watch.)
***automatically write '\0' to buf[15]
Extra
---------------------------------------------------------
strncpy(buf, EX_STR, 0);
result:string:01234 [strlen(buf):5, sizeof(buf):16]
buf[0] = 48
buf[1] = 49
buf[2] = 50
buf[3] = 51
buf[4] = 52
buf[5] = 0
buf[6] = 0
buf[7] = 0
buf[8] = 0
buf[9] = 0
buf[10] = 0
buf[11] = 0
buf[12] = 0
buf[13] = 0
buf[14] = 0
buf[15] = 0
buf[BUF_LEN] = 0  (secretly watch.)
Not write any.
Right usage
---------------------------------------------------------
buf[0] = 48
buf[1] = 49
buf[2] = 50
buf[3] = 51
buf[4] = 52
buf[5] = 53
buf[6] = 54
buf[7] = 55
buf[8] = 56
buf[9] = 57
buf[10] = 97
buf[11] = 98
buf[12] = 99
buf[13] = 100
buf[14] = 101
buf[15] = 0
buf[BUF_LEN] = 0  (secretly watch.)
strncpy(buf, EX_STR, BUF_LEN); after buf[BUF_LEN-1] = '\0';
検索用タグ C言語 strncpy 安全
PR
					
					
																				
										
					2012/06/30 (Sat.) Comment(0) C言語
Comments
	
	