【C言語】
free(&自動変数)はバグ
(Free of Memory not on the Heap)

warning: ‘free’ called on unallocated object ‘自動変数’

警告:自動変数の解放は未定義の動作
[-Wfree-nonheap-object]


■この記事の概要

この記事では、C言語でfree関数を誤ってスタック領域や部分解放に使用するリスクと、これによるエラーを防ぐための推奨方法を解説しています。


■自動変数を自分でfreeしてはいけません

#include    <stdio.h>
#include    <stdlib.h>
int main(void)
{
    int     自動変数 = 1024 ;
    
    printf("%d\n",自動変数);
    
    free(&自動変数);//★ダメ
}

自動変数は
自動的にメモリに配置され、
自動的に解放される変数のことなので、
free関数を使ってプログラマが自分で解放してはいけません。


■スタックはfreeで解放できません

warning: ‘free’ of ‘ptr’ which points to memory not on the heap

警告:ヒープ領域上にないメモリを指す ‘ptr’ をfreeした
[-Wanalyzer-free-of-non-heap]

#include    <stdlib.h>
static size_t  size ;
int main(void) {
    char    buf[100];
    char    *ptr ;
    if(size > 100)
        ptr = malloc(size) ;    //ヒープ領域
    else
        ptr = buf ;             //スタック領域    
    //
    // ~~~~
    //
    free(ptr) ;      //非ヒープ領域をfreeした
}

この例では size が100以下の時はヒープ領域(malloc()された領域)を指していないのに free(ptr) を実行してしまうバグです。
malloc()された領域の時のみfreeするように修正が必要です。

■ヒープ領域の部分freeできません

warning: ‘free’ of ‘&*p.mem1’ which points to memory not on the heap

警告:ヒープ領域上にないメモリを指す
‘&p->mem1’のfree
[-Wanalyzer-free-of-non-heap]

#include    <stdlib.h>
struct  tag     {
    int m1;
    int m2;
    int m3;
} ;
int  main(void){
    struct  tag *p = malloc(sizeof(struct tag)) ;
    //
    //~
    //
    free(&(p->m1)) ; //NG部分free
    free(&(p->m2)) ; //NG途中free
    free(&(p->m3)) ; //NG同上        
}

このコードでは 
p->m1だけfreeしたいのか、
p の指す先を全部freeしたいのか、
読み手にわかりません。

malloc()した領域を一部だけfreeする事はできません。
全部freeしたい場合は
free(&p->m1) ではなくて
free(p) としてください。

また、
free(&(p->m2))のように途中のfreeもできません。

参考:

CWE-590 ヒープ領域の不適切な解放

MEM34-C. 動的に割り当てられたメモリのみを解放する