【C言語】
バッファオーバーラン
(out-of-bounds)

warning: iteration 1024 invokes undefined behavior

警告:ループカウンタ 1024 で未定義動作
[-Waggressive-loop-optimizations]


■<と<=を間違える

static int  ary[1024];
int main(void){
    for(int i = 0 ; i <= 1024 ;i++){//★NG
        ary[i] = 0 ;
    }
}

●修正例1.<に変更する

static int  ary[1024];
int main(void){
    for(int i = 0 ; i < 1024 ;i++){
        ary[i] = 0 ;
    }
}

■要素数とサイズを間違える

#include <stdint.h>
static char aryC[1024];
static int  aryI[1024];
int main(void){
    //たまたま上手くいく例
    for(uint32_t i = 0 ; i < sizeof(aryC) ;i++){
        aryC[i] = 0 ;
    }
    //配列の要素数とサイズは違う
    for(uint32_t i = 0 ; i < sizeof(aryI) ;i++){//★NG
        aryI[i] = 0 ;
    }
}

要素数はサイズではありません。
sizeof(aryI) != 1024
sizeof(aryI) == sizeof(int)*1024 
です。

このコードではLP64モードの場合、4096回転するので
配列の領域外破壊が発生します。

●修正例2.

#include <stdint.h>
static char aryC[1024];
static int  aryI[1024];
int main(void){
    const uint32_t maxC = sizeof(aryC)/sizeof(aryC[0]);
    for(uint32_t i = 0 ; i < maxC ;i++){
        aryC[i] = 0 ;
    }
    
    const uint32_t maxI = sizeof(aryI)/sizeof(aryI[0]);
    for(uint32_t i = 0 ; i < maxI ;i++){
        aryI[i] = 0 ;
    }
}

配列の要素数を求める定石 sizeof(配列)/sizeof(配列[0])を使います。


■strcpyとmemcpyを間違える

char buf[1024];
void f1(void)
{
    //ダメ:空文字列””の後ろを領域外参照する
    memcpy(buf,"",sizeof(buf));
}
void f2(void)
{
    //推奨はしないがbufは全部0クリアされる。
    strncpy(buf,"",sizeof(buf));
}

文字列配列の初期化に 
f1()のようにmemcpy()を使用すると
空文字列””の後ろを参照してしまうので
文字列リテラル領域外参照となります。

f2()のようにstrncpy()を使用すると
領域外参照は発生しませんが無駄な動きをするので推奨はしません。

文字列配列の初期化をしたいならば全部0クリアする必要はなく
buf[0] = ‘\0’
と、先頭だけ初期化すれば必要十分です。