アロケータの作り方

STL標準のstd::allocatorには、アラインメントを操作する機能がないので
確保したいメモリのアイランメントを設定したい場合、自前でアロケータを作る必要がある

#include <malloc.h>

typedef unsigned long uint32;

// デフォで4バイトアラインメント
template <class T, uint32 N = 4>
class CAllocator : public std::allocator<T>
{
public:
	typedef uint32	size_type;
	typedef T*	pointer;
	typedef const T*	const_pointer;
	typedef T&	reference;
	typedef const T&	const_reference;
	typedef T		value_type;

	// メモリを割り当てる
	pointer allocate(size_type num, const void* hint = 0)
	{
		return (pointer)memalign(N, num * sizeof(T));
	}

	// メモリを解放する
	void deallocate(pointer p, size_type num)
	{
		free(p);
	}

	// 割当てることができる最大の要素数を返す
	size_type max_size() const
	{
		struct mallinfo memInfo = mallinfo();
		return memInfo.fordblks;
	}
};

max_sizeの処理が正しくないけど、スルーでお願いします^^
mallinfoは、構造体と関数の両方があるので、構造体として使用する場合、C++でもstructを付ける必要があります。

セーブとロードでの型違いは×

固定長のものはセーブとロードが同一環境であるならば、構造体にして
その構造体をそのままセーブ、ロードすることで問題ない。


しかし、可変長のものはそうはいかないので、可変した際の数やらなんやらを保存しなくてはいけない。
今回、std::mapを使っていたのもを保存したわけだが、前に容量が大きくなりすぎたので
型をunsigned intからunsigned shortに変更したことがある。


それで、セーブのときは、std::map::iterator::firstとstd::map::iterator::secondを
使えばよいので問題ないが、ロードの際は一度この値を読み込んだ後に
設定しなければいけない。
その読み込む際に、読み込む変数がunsigned int型で読み込んでいたため
読み込みにずれが生じてしまった。
可変長のデータを扱うときは注意しましょう。

ひどいプログラムを見た

こんなのがあった。一瞬何をやっているかわからなかった。

if (IsHoge()) {
	// いろいろ
} else if (IsHogeHoge());
else {
	// いろいろ
}


普通こうだろ

if (IsHoge()) {
	// いろいろ
} else if (!IsHogeHoge()) {
	// いろいろ
}

メモリプールを活用しよう

メモリが非常に厳しい環境でゲームを作る場合、最低でも1つメモリプールを作成しよう。
グローバルnewやmallocは通常のメモリからメモリを確保し、画像やサウンドなど
メモリ消費が多いものはメモリプールを使うようにする。
そうしないと、メモリの断片が発生し、24MBしかないPSPで最終的に600KBの領域すら確保できなくなることもある。


現在は4つのメモリプールを生成し、テクスチャー用、ファイル読み込み用、ファイル解凍用、その他用として活用してる。