【C言語】
realloc失敗によるメモリリーク防止法
(よくあるミスと対策)

(error) Common realloc mistake: ‘p’ nulled but not freed upon failureera

エラー:reallocに失敗したが古い領域は解放されていない[(error)memleakOnRealloc]

■この記事の概要

この記事は、realloc関数を使用する際のよくあるミスによるメモリリークについて詳しく解説しています。

特に、reallocの戻り値を同じポインタに割り当ててしまう問題や、メモリ領域を手動で解放する際の誤りに焦点を当て、それらの問題を回避するための適切なコーディング方法を紹介しています。

C言語のメモリ管理において安全で効率的な実装を目指す方に有用な情報です。

■reallocとは

reallocとは
ラーメンを頼んだ後で
食べ足りないので追加の替え玉を頼むように、

mallocした後でメモリが足りないので
追加のメモリをOSに頼む時に使います。

ここでは、reallocを使用する際によくやる
エラー処理で新旧ポインタが同じという
間違いを紹介します。

■新旧ポインタが同じ間違い

#include    <stdlib.h>
int main(void) {
    void    *p = malloc(256);
    if(p == NULL) {
        return  1;
    }
    //
    //~
    //
    p = realloc(p,1024);//よくある間違い新旧ポインタが同じ 
    if(p == NULL) {
        return  1;      //ここでメモリリーク発生
    }
    free(p);
}

p = realloc(p,1024);のようにrealloc()の第一引数と戻り値の変数を同じにしてはいけません。
realloc()失敗時に古い領域を指すpがNULLに上書きされるので古い領域が解放不能になります。

■古い領域を参照する間違い

warning: Use of memory after it is freed

警告:解放後メモリ参照
[unix.Malloc]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
    char *oldp = malloc(100);
    strcpy(oldp,"ABCDE");
    printf("昔:%s\n",oldp);

    char *newp = realloc(oldp,300);
    if(newp != oldp){
        printf("確保し直したメモリが違うアドレスだった\n");
        memcpy(newp,oldp,100);//★ダメ
        free(oldp);      //★ダメ
    }
    printf("今:%s\n",newp);
    free(newp);
    return 0;
}

realloc成功時の
古い領域から新しい領域へのデータの引っ越しと
古い領域の解放は
realloc関数がやるのであって
プログラマが自分で書いてはダメです。

手元のLinux環境では free(): double free detected in tcache 2
とエラーを吐いて異常終了しました。

参考:

ERR33-C. 標準ライブラリ関数のエラーを検出し対処する