malloc/free時のオーバーヘッドを最小化する方法

# 目的
　malloc/free関数を使用する場合に、オーバーヘッド（負荷）を最小化する方法について、理解する。

# 内容
　構造体用のメモリ（インスタンス）の割り当てと解放を繰り返す場合、オーバーヘッドが生じてしまう恐れがある。
そのため、構造体用のインスタンスをリストで管理することで、改善する。
- 構造体のインスタンスが不要の場合は、インスタンスをリストに保存しておく
- 構造体のインスタンスが必要な場合は、リストからインスタンスを使用する
- リストに何もない（インスタンスが全て使用されている）場合は、新しいインスタンスを作成する

以下のプログラムを用いて説明する。
- 構造体の定義
```
/* test6.h */
#include <stdio.h>

typedef struct _person{
    char* firstName;
    char* lastName;
    char* title;
    unsigned int age;
} Person;
```

- メイン処理
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test6.h"

#define LIST_SIZE 1
Person *list[LIST_SIZE];

/* プロトタイプ宣言 */
void initialiseList();
Person* getPerson();
void initializePerson(Person *person, const char* fn,
    const char* ln, const char* title, unsigned int age);
void deallocatePerson(Person *person);
void displayPerson(Person *person);
Person* returnPerson(Person *person);

int main(void){
    initialiseList();
    Person* ptrPerson;

    ptrPerson = getPerson();
    initializePerson(ptrPerson, "Ralph", "Fitsgerald", "Mr.", 35);
    displayPerson(ptrPerson);
    returnPerson(ptrPerson);
    return 0;
}

void initialiseList(){
    for(int i = 0; i < LIST_SIZE; i++){
        list[i] = NULL;
    }
}

Person* getPerson(){
    for(int i = 0; i < LIST_SIZE; i++){
        if(list[i] != NULL){
            Person* ptr = list[i];
            list[i] = NULL;
            return ptr;
        }
    }
    Person* person = (Person*)malloc(sizeof(Person));
    return person;
}

void initializePerson(Person *person, const char* fn,
    const char* ln, const char* title, unsigned int age){
    person->firstName = (char*)malloc(strlen(fn)+1);
    strcpy(person->firstName, fn);
    person->lastName = (char*)malloc(strlen(ln)+1);
    strcpy(person->lastName, ln);
    person->title = (char*)malloc(strlen(title)+1);
    strcpy(person->title, title);
    person->age = age;
}

void deallocatePerson(Person *person){
    free(person->firstName);
    free(person->lastName);
    free(person->title);
}

void displayPerson(Person *person){
    printf("%s %s, %s, %d\n", person->firstName, person->lastName, person->title, person->age);
}

Person* returnPerson(Person *person){
    for(int i = 0; i < LIST_SIZE; i++){
        if(list[i] == NULL){
            list[i] = person;
            return person;
        }
    }
    deallocatePerson(person);
    free(person);
    return NULL;
}
```

プログラムの流れを説明する。
- リストの定義：構造体Person型のリスト配列ポインタを定義する
    - #define LIST_SIZE 1：リストに保存するインスタンスの数1
    - Person *list[LIST_SIZE]：構造体Person型のリスト配列
- メイン関数
    1. nitialiseList関数でリストを初期化→インスタンスが作成されていない状態
    2. 構造体Person型のポインタptrPersonを作成
    3. ptrPersonにgetPerson関数の返り値が代入される
    ・ リストに構造体がある場合は、構造体Person型のポインタptrにリストが代入され、そのリストはNULLになる→リストからインスタンスが使用される
    ・ リストに何もない場合は、構造体Person型のポインタpersonにメモリが確保される→新しいインスタンスが作成される
    4. initializePerson関数でptrPersonの指す構造体Personのメンバ変数に値が代入される
    5. displayPerson関数でptrPersonの指す構造体Personの中身を表示
    6. returnPerson関数の実行
    ・ リストに何もない場合は、リストに構造体Person型のポインタpresonが代入される
    ・ リストが全て使用されている場合は、構造体Person型のポインタpersonのインスタンスを解放する

# 所感
malloc、free関数をたくさん使用すると、メモリ容量が減ってしまい、容量が無駄になる。そのため、リストを作成することによって、必要な分だけインスタンスを作成し、リストの上限になるとインスタンスを解放することで、メモリ容量の効率化につながると感じた。

## 参照
詳説Cポインタ　P152、153