深入解析Nginx的pcre库及相关注意事项
来源:互联网 发布:红河烟草集团知乎 编辑:程序博客网 时间:2024/06/06 10:38
http://blog.xiuwz.com/2011/11/29/nginx-pcre-conflict/
背景:最近新开发一个Nginx扩展模块,需要结合另外一个C++库进行扩展开发,该C++库中用到了pcre库。在编译后,发现总是会core,日志中出现明显如下的错误“pcre(****) failed to get memory”。针对该C++库,单独编写额外的程序处理,则不会出现任何问题。所以问题很诡异。
针对该问题,需要了解两个方面,1、pcre库。2、nginx中pcre库的处理(编译过nginx的都支持,一般情况下nginx都依赖到了pcre)。
pcre库相关
通过学习pcre库的api:http://regexkit.sourceforge.net/Documentation/pcre/pcreapi.html
基本上了解到pcre库中会动态申请相关内存,为了保证内存的线程安全,pcre提供了以下内存管理的函数指针:
1
2
3
4
5
void
*(*pcre_malloc)(
size_t
);
void
(*pcre_free)(
void
*);
void
*(*pcre_stack_malloc)(
size_t
);
void
(*pcre_stack_free)(
void
*);
int
(*pcre_callout)(pcre_callout_block *);
默认情况下,都直接采用了原生的malloc和free。
1
2
3
4
5
PCRE_EXP_DATA_DEFN
void
*(*pcre_malloc)(
size_t
) =
malloc
;
PCRE_EXP_DATA_DEFN
void
(*pcre_free)(
void
*) =
free
;
PCRE_EXP_DATA_DEFN
void
*(*pcre_stack_malloc)(
size_t
) =
malloc
;
PCRE_EXP_DATA_DEFN
void
(*pcre_stack_free)(
void
*) =
free
;
PCRE_EXP_DATA_DEFN
int
(*pcre_callout)(pcre_callout_block *) = NULL;
Nginx中Pcre处理
Nginx内部对Pcre库进行了再次封装,具体在src/core/ngx_regex.c文件中。nginx_regex_*函数基本上对pcre所有的接口都进行了二次封装。其中最关键的是对内存的处理,该内存处理采用了Nginx内置的内存池概念。
具体如下,首先,重置pcre内存管理的接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void
ngx_regex_init(
void
)
{
pcre_malloc = ngx_regex_malloc;
pcre_free = ngx_regex_free;
}
static
void
* ngx_libc_cdecl ngx_regex_malloc(
size_t
size)
{
ngx_pool_t *pool;
#if (NGX_THREADS)
//线程相关处理
#else
pool = ngx_pcre_pool;
#endif
if
(pool) {
return
ngx_palloc(pool, size);
}
return
NULL;
}
static
void
ngx_libc_cdecl ngx_regex_free(
void
*p)
{
return
;
}
然后,在需要用到的地方进行初始化调用。
1
2
3
4
5
6
7
8
9
10
11
ngx_int_t
ngx_regex_compile(ngx_regex_compile_t *rc)
{
...
ngx_regex_malloc_init(rc->pool);
re = pcre_compile((
const
char
*) rc->pattern.data, (
int
) rc->options,
&errstr, &erroff, NULL);
/* ensure that there is no current pool */
ngx_regex_malloc_done();
...
}
结论
至此,比较清楚问题是出在Nginx的pcre内存管理和第三方默认的pcre内存管理有了冲突。所以解决方案就是在调用第三方的的地方进行pcre内存函数指针重置。如下所示:
1
2
3
4
5
6
7
8
9
void
*(*old_pcre_malloc)(
size_t
);
void
(*old_pcre_free)(
void
*);
old_pcre_malloc = pcre_malloc;
old_pcre_free = pcre_free;
pcre_malloc =
malloc
;
pcre_free =
free
;
/**调用第三方库的函数接口*/
pcre_malloc = old_pcre_malloc;
pcre_free = old_pcre_free;
- 深入解析Nginx的pcre库及相关注意事项
- 正则库相关及windows-VS-C++环境下pcre && pcre++的编译和使用
- lighttpd及相关依赖库pcre/bzip2在ubuntu下的安装
- 安装Nginx时遇到的pcre库问题
- Nginx+pcre部署及配置步骤
- PCRE的安装及使用
- PCRE的安装及使用
- 安装nginx前的pcre中报错
- Centos6.5安装Nginx的教程 先安装nginx依赖的库pcre
- xml的相关概念及注意事项
- 包的定义及相关注意事项
- ubuntu下安装nginx时PCRE库、zlib库、OpenSSL库的安装
- lighttpd及pcre的交叉编译
- C/C++高效的正则表达式库PCRE/PCRE++
- Mac nginx PCRE
- nginx编译缺少pcre
- nginx 安装缺少pcre,zlib,openssl的解决
- ubuntu安装nginx依赖库zlib,pcre,openssl
- 从零开始学习Linux 基础(二)—磁盘、分区与文件系统
- apache中开启Gzip和expires,优化页面访问速度
- codeforces Polo the Penguin and Strings 思维问题代码链接
- C++通用Functor仿函数 LOKI库中的模版使用以及设计新思维
- regular expression
- 深入解析Nginx的pcre库及相关注意事项
- java的小知识
- 女人写给男人的10句肺腑之言
- 听道笔记-03-31-2013-《耶稣的复活》---远志明
- 3Sum Closest
- 黑马程序员_常用集合类
- CSDN怎么比较快的获得积分
- 4Sum
- 为iPhone App切图的技巧