目的
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型のリスト配列
- メイン関数
- nitialiseList関数でリストを初期化→インスタンスが作成されていない状態
- 構造体Person型のポインタptrPersonを作成
- ptrPersonにgetPerson関数の返り値が代入される
・ リストに構造体がある場合は、構造体Person型のポインタptrにリストが代入され、そのリストはNULLになる→リストからインスタンスが使用される
・ リストに何もない場合は、構造体Person型のポインタpersonにメモリが確保される→新しいインスタンスが作成される - initializePerson関数でptrPersonの指す構造体Personのメンバ変数に値が代入される
- displayPerson関数でptrPersonの指す構造体Personの中身を表示
- returnPerson関数の実行
・ リストに何もない場合は、リストに構造体Person型のポインタpresonが代入される
・ リストが全て使用されている場合は、構造体Person型のポインタpersonのインスタンスを解放する
所感
malloc、free関数をたくさん使用すると、メモリ容量が減ってしまい、容量が無駄になる。そのため、リストを作成することによって、必要な分だけインスタンスを作成し、リストの上限になるとインスタンスを解放することで、メモリ容量の効率化につながると感じた。
参照
詳説Cポインタ P152、153