Memset

memsetとは、標準Cライブラリのヘッダー <string.h> (文字列操作関数群) で定義されているC言語の関数である。

指定されたポインタが指すオブジェクトの先頭から、指定されたバイト数分に、指定した文字データを書き込むはたらきをする。
つまり、ポインタが指しているメモリブロック先頭から指定されたサイズの連続領域において、1バイトごとに文字をセットする。

 形式 
#include <string.h>

void *memset(void *s, int c, size_t n);

memset関数は、c の値を型に変換し、s が指すオブジェクトの最初の n 文字にそれぞれコピーする。

 利用例 
次の例は、char型配列（文字列）を文字'@'で埋めるプログラムである。

#include <stdio.h>
#include <string.h>

#define STR_BUF_SIZE 10

int main(void) {
    char a[STR_BUF_SIZE];
    memset(a, '@', STR_BUF_SIZE); /* 配列の要素全てを文字'@'で埋める */
    a[STR_BUF_SIZE - 1] = '\0';
    printf("a = \"%s\"\n", a);
    return 0;
}

配列や構造体のメモリブロックをゼロで埋める際は、以下の様にmemsetを用いる。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define STR_BUF_SIZE 100

int main(void) {
    char *s = NULL;
    s = (char*)calloc(STR_BUF_SIZE, sizeof(char));
    strcpy(s, "password1");
    printf("s = \"%s\"\n", s);
    /* メモリ領域から古いパスワードの痕跡を完全にクリアして空文字列化する。 */
    memset(s, 0, STR_BUF_SIZE);
    /* 新しいパスワードをコピーする。 */
    strcpy(s, "pass2");
    printf("s = \"%s\"\n", s);
    /* 単純にゼロ終端文字列で空文字列を実現する場合、先頭にNUL文字を代入するか、空文字列をコピーするだけでもよいが、痕跡が残る。 */
#if 0
    s[0] = '\0';
#else
    strcpy(s, "");
#endif
    printf("s = \"%s\"\n", s);
    printf("s[1] = '%c'\n", s[1]);
    memset(s, 0, STR_BUF_SIZE);
    free(s);
    return 0;
}

ただしmemset呼び出しはコンパイラ最適化によって除去されることもある。機密性の高い情報をメモリからクリアするなど、セキュリティ脆弱性の解消を目的とする場合は、C11オプション関数のmemset_sや、Windows APIのSecureZeroMemoryなどを使用する。処理系によっては型修飾子を使用することで最適化を抑止し、memset呼び出しが削除されることを防ぐ方法もあるが、移植性はないIPA ISEC　セキュア・プログラミング講座：C/C++言語編　第7章 データ漏えい対策：メモリクリア失敗対策MSC06-C. コンパイラの最適化に注意する。

 実装例 
memsetを自前で定義したい場合は、以下の様に実装する。

/* memsetと区別するため、大文字を使用 */
void *MemSet(void *buf, int c, size_t num) {
    unsigned char *ptr = (unsigned char *)buf;
    const unsigned char ch = (unsigned char)c;

    while (num--)
        *ptr++ = ch;

    return buf;
}

 脚注 
 注釈 

 出典 

 関連項目 
 C言語
 標準Cライブラリ
 プログラミング言語

 参考文献 


 外部リンク 


Category:標準Cライブラリ