C言語の安全な文字列コピーは、strcpyよりもstrncpy、そしてstrlcpyが良い

C言語を触っている時に文字列コピーを行いたい場合がありますが、その時にどの関数を使えば良いのか、の考察をしていく。

strcpy

文字列コピーで代表的なのが、strcpy。最もシンプルな関数だが、最も安全性が低いともいえる。

ポイントとしては、コピーされる側の文字列は、char str[30]のように配列型とかmallocでメモリを確保した文字列にしておくこと。char *strのようにポインタ型の文字列だと上手く処理できない。

    char str[30] = "../public/index.html";
    char *str2 = "Legend";
    
    strcpy(str, str2);
    printf("%s", str); // Legend

strcpyを使うと、元の文字列は上書きされる。もし、文字列を連結させたい場合はstrcatを使おう。戻り値は、コピー後の文字列の先頭ポインタになる。

参考:C言語関数辞典 - strcpy

strcpyの問題点

strcpyの問題点は、バッファーオーバーフローを引き起こす危険があることだ。バッファーオーバーフローとは、用意したメモリ量よりも多いデータを格納しようとした時に起こる現象で、基本的にSegment Failtが発生する。

strcpyの場合は、コピー先の文字列の配列が30なのに、36文字の文字列をコピーしようとした場合に起こる。

strncpy

strcpyの欠点を補うという意味で使われるのが、strncpyとなる。(完璧な関数とは言えないけど)

strcpyと違う点は、コピーする文字列の文字数を指定できる点。

char *strncpy(
    char * restrict s1,
    const char * restrict s2
    size_t n
);

とは言っても、完全にバッファーバーフローを防げるわけではないので、if(s1_size > s2_size)のようにコピー先とコピー元のメモリ量を比較して、コピー元の方がメモリ量が小さい場合は処理を進める、と言う風にする必要がある。

あと、strcpystrncpyも文字列の最後に、プログラマがs1[30] = '\0';のように手動でヌル文字を付ける必要がある。

参考:C言語関数辞典 - strncpy