【问题标题】:What is proper use of Apache method apr_pool_create_ex in Delphi XE?Delphi XE 中 Apache 方法 apr_pool_create_ex 的正确用法是什么?
【发布时间】:2011-03-25 19:19:00
【问题描述】:

Delphi XE 中 Apache 方法 apr_pool_create_ex 的正确用法是什么?

我以前创建过 Apache 模块,但都是处理程序。现在我正在开发一个服务提供者。已经创建了一个骨架模块,Apache 正在调用我的 child_init 回调方法。在 child_init 方法中,我成功调用了 ap_pool_create_ex*(返回 APR_SUCCESS),但是在离开 child_it 调用后,我在第三个或第四个工作线程的(httpd.exe)生成期间收到访问冲突(第三个在事件中显示日志)。

procedure provider_child_init(pchild: Papr_pool_t; s: Pserver_rec); cdecl;
var
  rv  : apr_status_t;
  mypool : Papr_pool_t;
begin
  rv := -1;
  rv := apr_pool_create_ex(@mypool,pchild,nil,nil);
end;

AV 消息是:

“项目 C:\Apache2.2\bin\http.exe 连续提出太多 例外:'访问冲突在 0x00000000:读取地址 0x00000000'。进程停止。使用步骤 或运行以继续”

事件日志:

…
Thread Start: Thread ID: 5652. Process httpd.exe (4212)
Thread Start: Thread ID: 5132. Process httpd.exe (4212)
Thread Start: Thread ID: 5988. Process httpd.exe (4212) 

注意:AV 出现在线程 ID 5988 和 4212 是父 httpd.exe 进程。

  • Windows“libapr-1.dll”不包含“apr_pool_create”,这就是我使用“_ex”版本的原因。知道为什么缺少 apr_pool_create 吗?我看到 apr_pool_create 在其他成功的 modules 中使用,尽管它们是用“C”编写的。

操作系统:Windows 7 企业版 64 位

Apache:2.2.17.0

IDE:Delphi XE

【问题讨论】:

  • 关于 apr_pool_create 丢失的原因,它可能不是从 DLL 导出的,因为你可以用它做的任何事情你也可以用 apr_pool_create_ex 做,等等。不过,用 C 编写的模块仍然可以静态链接。

标签: delphi delphi-xe apache-modules


【解决方案1】:

您对函数的翻译是否正确? Delphi XE Version Insight(Subversion 插件)声明如下:

type
  PAprPool = ^TAprPool;
  TAprPool = THandle;
  PAprAllocator = ^TAprAllocator;
  TAprAllocator = THandle;
  TAprAbortFunc = function(retcode: Integer): Integer; stdcall;

var
  apr_pool_create_ex: function(out newpool: PAprPool; parent: PAprPool; abort_fn: TAprAbortFunc;
    allocator: PAprAllocator): TAprStatus; stdcall;

还要检查您的 provider_child_init 回调是否真的应该声明为 cdecl 而不是 stdcall

此外,还有一些想法,因为您遇到了空指针访问冲突。根据apr源码comment

  • 如果(如您的情况)您向它传递一个 nil 分配器,则将使用父池的分配器。我假设如果父池为 nil,则分配器不能为 nil。
  • 如果池无法分配内存,abort_fn 将被回调。你没有通过它;也许池试图调用它是因为它无法分配内存?
  • 我认为您不能从不同的线程访问同一个池。您可能必须为每个线程创建一个单独的池。

【讨论】:

  • 感谢您的帮助。我使用的是 apr_pool_create_ex 的 FreePascal 定义(不包括在 Delphi 中)。似乎第一个参数是罪魁祸首。我定义了一个 abort_fn 但它没有被调用,因此作为尝试使其工作的一部分,我将它设置为 nil 以查看会发生什么。顺便说一句,provider_child_init 函数被定义为 cdecl。
猜你喜欢
  • 2011-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 2020-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多