kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

メモリプールを使ってみる

APR(Apache Portable Runtime)のメモリプール機能を使ってみました。メモリプールを利用して、メモリを確保する流れは次のようになるようです。

  1. apr_pool_create関数を使用して、メモリプールを作成します。
  2. apr_pallocまたはapr_pcalloc関数を使用して、メモリプールからメモリを確保します。
  3. 確保したメモリを使用します。
  4. apr_pool_clearまたはapr_pool_destroy関数を使用して、メモリプールを破棄します。

上記でメモリの解放という手順は存在しません。APRではメモリプールの単位でメモリを管理していて、メモリ解放は適宜実施してくれるようです。

上記では、メモリプールを1つしか作らない流れですが、メモリプールは複数作成する事が可能で、各メモリプールは、親子関係を付ける事が出来ます。

プログラム例

親子関係のメモリプールを作成し、メモリ確保し、確保したメモリに文字列を書き込むプログラムを作成してみました。

try_apr_pools.c

/*
 * APRのメモリプール機能を使ってみました。
 */
#include <stdio.h>
#include "apr_pools.h"

int main(int argc, char **argv) {
	
	apr_status_t status = APR_SUCCESS;
	apr_pool_t *pool = NULL;
	apr_pool_t *pool2 = NULL;
	void *ptr = NULL;
	
	// APRを初期化する。
	apr_initialize();
	
	// 親プールを作成する。
	status = apr_pool_create(&pool, NULL);
	if (status == APR_SUCCESS) {
		
		// メモリを確保する。
		ptr = apr_pcalloc(pool, 10);
		
		// 子供プールを作成する。
		status = apr_pool_create(&pool2, pool);
		if (status == APR_SUCCESS) {
			
			// メモリを確保する。
			ptr = apr_pcalloc(pool2, 10);
			if (ptr != NULL) {
				// 書き込み
				strcpy((char*)ptr, "Hello");
				
				printf("書き込み結果 [%s]\n", ptr);
			}
			
			// メモリを解放する。
			apr_pool_clear(pool2);
		}
		else {
			printf("子供プールを作成できませんでした。\n");
		}
		
		// プールを破棄する。
		apr_pool_destroy(pool);
	}
	else {
		printf("親プールを作成できませんでした。\n");
	}
	
	// APRを終了する。
	apr_terminate();
	
	return 0;
}

実行結果

$ ./try_apr_pools.exe
書き込み結果 [Hello]

補足

参考サイト

Memory Pool Functions
http://apr.apache.org/docs/apr/1.2/group__apr__pools.html

動作環境

OS : Windows XP, Cygwin
APR Version : 1.2.12

ハッシュテーブルを使ってみる

APR(Apache Portable Runtime)のハッシュ機能を使ってみました。ハッシュ機能を利用する場合の手順は次のようになるようです。

  1. apr_pool_create関数を使用して、ハッシュ機能で使用するメモリプールを作成します。
  2. apr_hash_make関数を使用して、ハッシュテーブルを作成します。
  3. apr_hash_set関数を使用して、ハッシュテーブルに要素を追加します。
  4. apr_hash_set,apr_hash_get,apr_hash_first,apr_hash_next,apr_hash_this,apr_hash_count関数などを使用して、各要素にアクセスします。
  5. ハッシュテーブルを使い終わったら、apr_pool_clearまたはapr_pool_destroy関数を使用して、メモリプールを破棄します。

プログラム例

ハッシュテーブルへ、文字列のキーと値のペアを3つ登録し、各要素の取得、変更、削除をするサンプルプログラムを作成してみました。

try_apr_hash.c

#include <stdio.h>
#include "apr_hash.h"

void print_hash(apr_pool_t *pool, apr_hash_t *hash) {
	apr_hash_index_t *hash_index = NULL;
	const void *key = NULL;
	void *val = NULL;
	
	// 要素数を出力する。
	printf("要素数:[%d]\n", apr_hash_count(hash));

	// 内容を出力する。
	hash_index = apr_hash_first(pool, hash);
	while (hash_index) {
		apr_hash_this(hash_index, &key, NULL, &val);
		printf("key=[%s], value=[%s]\n", (char*)key, (char*)val);
		hash_index = apr_hash_next(hash_index);
	}
}

int main(int argc, char **argv) {
	
	apr_status_t status = APR_SUCCESS;
	apr_pool_t *pool = NULL;
	apr_hash_t *hash = NULL;
	char *key1 = "key1";
	char *key2 = "key2";
	char *key3 = "key3";
	char *value1 = "value1";
	char *value2 = "value2";
	char *value3 = "value3";
	char *value4 = "value4";
	
	// APRを初期化する。
	apr_initialize();
	
	// メモリプールを作成する。
	status = apr_pool_create(&pool, NULL);
	if (status == APR_SUCCESS) {
		
		// ハッシュを作成する。
		hash = apr_hash_make(pool);
		
		// 要素を追加する。
		apr_hash_set(hash, key1, APR_HASH_KEY_STRING, value1);
		apr_hash_set(hash, key2, APR_HASH_KEY_STRING, value2);
		apr_hash_set(hash, key3, APR_HASH_KEY_STRING, value3);
		
		printf("キー[%s]の値=[%s]\n", key1, (char*)apr_hash_get(hash, key1, APR_HASH_KEY_STRING));
		
		// ハッシュの内容を出力する。
		print_hash(pool, hash);
		
		// 要素を変更する。
		apr_hash_set(hash, key2, APR_HASH_KEY_STRING, value4);
		
		// ハッシュの内容を出力する。
		print_hash(pool, hash);
		
		// 要素を削除する。
		apr_hash_set(hash, key2, APR_HASH_KEY_STRING, NULL);
		
		// ハッシュの内容を出力する。
		print_hash(pool, hash);
	}
	else {
		printf("メモリプールを作成できませんでした。\n");
	}
	
	// APRを終了する。
	apr_terminate();
	
	return 0;
}

実行結果

$ ./try_apr_hash.exe
キー[key1]の値=[value1]
要素数:[3]
key=[key1], value=[value1]
key=[key2], value=[value2]
key=[key3], value=[value3]
要素数:[3]
key=[key1], value=[value1]
key=[key2], value=[value4]
key=[key3], value=[value3]
要素数:[2]
key=[key1], value=[value1]
key=[key3], value=[value3]

補足

apr_hash_set関数について
引数にキーと値のポインタを渡します。ハッシュテーブルの各要素は、ポインタで参照される領域をそのまま使用するようです。そのため、呼び出し側で用意したキーと値の領域は、ハッシュテーブルを使い終わるまで、保持しておく必要があるようです。

参考サイト

Apache Portable Runtime: Hash Tables
http://apr.apache.org/docs/apr/1.2/group__apr__hash.html

動作環境

OS : Windows XP, Cygwin
APR Version : 1.2.12

Array機能を使ってみる

APR(Apache Portable Runtime)のArray機能で動的配列を使ってみました。Array機能を利用する場合の手順は次のようになるようです。

  1. apr_pool_create関数を使用して、Array機能で使用するメモリプールを作成します。
  2. apr_array_make関数を使用して、apr_array_header_tを作成します。
  3. apr_array_push関数を使用して、要素を追加します。
  4. apr_is_empty_array, apr_array_push, apr_array_pop関数など、またapr_array_header_t構造体の各要素を使用して、配列の各要素にアクセスします。
  5. apr_array_headerを使い終わったら、apr_pool_clearまたはapr_pool_destroy関数を使用して、メモリプールを破棄します。

プログラム例

try_apr_array.c

/*
 * APR Array機能
 * 新規作成:2008/01/14
 */
#include <stdio.h>
#include "apr_tables.h"

void print_array(apr_array_header_t *arr) {
	int i = 0;
	int *val_ptr = NULL;
	
	if (apr_is_empty_array(arr)) {
		printf("要素はありません。\n");
	}
	else {
		// Arrayの内容を出力する。
		for (i = 0; i < arr->nelts; i++) {
			val_ptr = (int*)(arr->elts + (arr->elt_size * i));
			printf("要素[%d]の値:[%d]\n", i, *val_ptr);
		}
	}
}

int main(int argc, char **argv) {
	
	apr_status_t status = APR_SUCCESS;
	apr_pool_t *pool = NULL;
	apr_array_header_t *arr = NULL;
	int *val_ptr = NULL;
	
	// APRを初期化する。
	apr_initialize();
	
	// メモリプールを作成する。
	status = apr_pool_create(&pool, NULL);
	if (status == APR_SUCCESS) {
		
		// int型要素のArrayを作成する。
		arr = apr_array_make(pool, 0, sizeof(int));
		
		// 要素を追加する。
		val_ptr = apr_array_push(arr);
		*val_ptr = 10;
		val_ptr = apr_array_push(arr);
		*val_ptr = 20;
		val_ptr = apr_array_push(arr);
		*val_ptr = 30;
		
		// Arrayの内容を出力する。
		print_array(arr);
		
		// 2番目の要素を変更する。
		val_ptr = (int*)(arr->elts + (arr->elt_size * 1));
		*val_ptr = 21;
		
		// Arrayの内容を出力する。
		print_array(arr);
		
		// 要素を削除する。
		apr_array_pop(arr);
		
		// Arrayの内容を出力する。
		print_array(arr);
		
		// メモリプールを破棄します。
		apr_pool_destroy(pool);
	}
	else {
		printf("メモリプールを作成できませんでした。\n");
	}
	
	// APRを終了する。
	apr_terminate();
	
	return 0;
}

実行結果

$ ./try_apr_array.exe
要素[0]の値:[10]
要素[1]の値:[20]
要素[2]の値:[30]
要素[0]の値:[10]
要素[1]の値:[21]
要素[2]の値:[30]
要素[0]の値:[10]
要素[1]の値:[21]

補足

参考サイト

Apache Portable Runtime: Table and Array Functions
http://apr.apache.org/docs/apr/1.2/group__apr__tables.html

井上の日誌 -Apacheの話-(2006-03-30)
https://www.codeblog.org/blog/inoue/20060330.html

動作環境

OS : Windows XP, Cygwin
APR Version : 1.2.12

Table機能を使ってみる

APR(Apache Portable Runtime)のTable機能を使ってみました。Table機能を利用する場合の手順は次のようになるようです。

  1. apr_pool_create関数を使用して、Table機能で使用するメモリプールを作成します。
  2. apr_table_make関数を使用して、apr_table_tを作成します。
  3. 次の関数を使用して、要素を操作します。
  4. apr_table_tを使い終わったら、apr_pool_clearまたはapr_pool_destroy関数を使用して、メモリプールを破棄します。

主要な要素操作の関数

関数 概要
apr_table_add 要素を追加します。キーが重複しても場合、異なる要素として追加します。キーと値は内部的にコピーされます。
apr_table_addn apr_table_addと同様ですが、キーと値は内部的にコピーされません。
apr_table_clear 全要素を削除します。
apr_table_get 指定されたキーに一致する要素を取得します。
apr_table_set 要素を登録します。キーが重複する場合、上書きになります。キーと値は内部的にコピーされます。
apr_table_setn apr_table_setと同様ですが、キーと値は内部的にコピーされません。
apr_table_unset 要素を1つ削除します。
apr_table_elts 全要素(apr_table_entry_t)の配列(apr_array_header_t)を取得します。

プログラム例

try_apr_table.c

/*
 * APR Table機能
 * 新規作成:2008/01/14
 */
#include <stdio.h>
#include "apr_tables.h"

void print_table(apr_table_t *table) {
	if (apr_is_empty_table(table)) {
		printf("要素はありません。\n");
	}
	else {
		const apr_array_header_t *arr = apr_table_elts(table);
		int i;
		for (i = 0; i < arr->nelts; i++) {
			apr_table_entry_t *entry =
				(apr_table_entry_t *)(arr->elts + (arr->elt_size * i));
			printf("%d番目の要素:キー=[%s],値=[%s]\n",
				i, entry->key, entry->val);
		}
	}
}

int main(int argc, char **argv) {
	char key1[] = "key1";
	char key2[] = "key2";
	char key3[] = "key3";
	char val1[] = "value1";
	char val2[] = "value2";
	char val3[] = "value3";
	
	// APRを初期化する。
	apr_initialize();
	
	// メモリプールを作成する。
	apr_pool_t *pool = NULL;
	apr_status_t status = apr_pool_create(&pool, NULL);
	if (status == APR_SUCCESS) {
		
		// ------------------------------
		// Tableの作成
		// ------------------------------
		
		// Tableを作成する。
		// 初期領域サイズは、要素5個分とした。
		apr_table_t *table = apr_table_make(pool, 5);
		
		// 要素を登録する。
		apr_table_set(table, key1, val1);
		apr_table_set(table, key2, val2);
		apr_table_set(table, key3, val3);
		
		// 内容を出力する。
		print_table(table);
		
		// ------------------------------
		// 要素の変更
		// ------------------------------
		
		printf("変更前:[%s]\n", apr_table_get(table, key2));
		apr_table_set(table, key2, "Hello");
		printf("変更後:[%s]\n", apr_table_get(table, key2));
		
		// ------------------------------
		// 要素の削除
		// ------------------------------
		
		printf("要素の削除\n");
		apr_table_unset(table, key2);
		print_table(table);
		
		// ------------------------------
		// 全要素のクリア
		// ------------------------------
		printf("要素のクリア\n");
		apr_table_clear(table);
		print_table(table);
		
		// メモリプールを破棄します。
		apr_pool_destroy(pool);
	}
	else {
		printf("メモリプールを作成できませんでした。\n");
	}
	
	// APRを終了する。
	apr_terminate();
	
	return 0;
}

実行結果

$ ./try_apr_table.exe
0番目の要素:キー=[key1],値=[value1]
1番目の要素:キー=[key2],値=[value2]
2番目の要素:キー=[key3],値=[value3]
変更前:[value2]
変更後:[Hello]
要素の削除
0番目の要素:キー=[key1],値=[value1]
1番目の要素:キー=[key3],値=[value3]
要素のクリア
要素はありません。

補足

参考サイト

Apache Portable Runtime: Table and Array Functions
http://apr.apache.org/docs/apr/1.2/group__apr__tables.html

井上の日誌 -Apacheの話-(2006-04-05)
https://www.codeblog.org/blog/inoue/20060405.html

動作環境

OS : Windows XP, Cygwin
APR Version : 1.2.12

Windowsのエディタを起動する関数

Cygwinのコマンドライン上から、普段使いなれたWindows用エディタを起動したくなりました。

私が愛用しているエディタは、「サクラエディタ」ですが、このエディタをCygwin上からコマンド実行で起動する関数を作成しました。下記のようになります。

この関数を~/.bashrcに記述して使う事で、ちょっと便利になりました!

# サクラエディタ起動 関数
# 2008/01/14
alias _sakura="/cygdrive/c/Program\ Files/sakura/sakura.exe"
function sakura() {
	if [[ "$#" == "0" ]]
	then
		_sakura &
	else
		for path in $*
		do (
			_sakura `cygpath -aw $path` &
		)
		done
	fi
}