参考: Re: Access violation from palloc, Visual Studio 2005, C-language function
include/server/utils/palloc.h に定義があります。
/* * Type MemoryContextData is declared in nodes/memnodes.h. Most users * of memory allocation should just treat it as an abstract type, so we * do not provide the struct contents here. */ typedef struct MemoryContextData *MemoryContext; /* * CurrentMemoryContext is the default allocation context for palloc(). * We declare it here so that palloc() can be a macro. Avoid accessing it * directly! Instead, use MemoryContextSwitchTo() to change the setting. */ extern DLLIMPORT MemoryContext CurrentMemoryContext; /* * Fundamental memory-allocation operations (more are in utils/memutils.h) */ extern void *MemoryContextAlloc(MemoryContext context, Size size); extern void *MemoryContextAllocZero(MemoryContext context, Size size); extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size); #define palloc(sz) MemoryContextAlloc(CurrentMemoryContext, (sz)) #define palloc0(sz) MemoryContextAllocZero(CurrentMemoryContext, (sz))MemoryContextAlloc や CurrentMemoryContext は、インポートライブラリを利用して postgres.exe プロセスからインポートします。
---
結論から申しますと、つぎのようにあるべきが、
extern __declspec (dllimport) MemoryContext CurrentMemoryContext;
BUILDING_DLL を定義することで、つぎのように変化することが問題でした。
extern __declspec (dllexport) MemoryContext CurrentMemoryContext;
---
それでは納得できないこともあろうかと、アセンブラレベルで解析もしました。
palloc するだけの C 関数:
PG_FUNCTION_INFO_V1(ddtest); Datum ddtest(PG_FUNCTION_ARGS) { palloc(0x123456); PG_RETURN_NULL(); }まず、
extern __declspec (dllimport) MemoryContext CurrentMemoryContext; となる場合。
緑下線を引いた部分 100470F8 が CurrentMemoryContext の実体のアドレスです。そこに意味のあるコードはありませんが一応。88 87 04 00 の部分が MemoryContextSwitchTo を呼び出すことで、本来の値に書き換えられるわけです。
つぎに、
extern __declspec (dllexport) MemoryContext CurrentMemoryContext; となる場合。
緑下線を引いた部分が <CurrentMemoryContext> になっています。一見これが正解じゃないかと思いますが、参照先は jmp dword ptr [0x100470f8] の命令コードです。
0x70f825ff に 4 を足した 0x70f82603 にアクセスしようとして、access violation が発生することが冒頭のエラーにつながります。
『postgres.exe の 0x005fbb4a で初回の例外が発生しました: 0xC0000005: 場所 0x70f82603 を読み込み中にアクセス違反が発生しました。』
外部の exe/dll からインポートする変数は、__declspec (dllimport) を使いましょう。
0 件のコメント:
コメントを投稿