From 1eb46265860c7ec4f836a3983d422dcb04f6cc63 Mon Sep 17 00:00:00 2001 From: ubuntu14 Date: Fri, 11 Dec 2015 08:58:30 +0800 Subject: [PATCH] xml parser supporting CDATA; fixed memory leak bugs in db_mysql class in multi-threads mode --- lib_acl/changes.txt | 3 + lib_acl/include/stdlib/acl_dll.h | 1 + lib_acl/include/xml/acl_xml.h | 36 +++-- lib_acl/include/xml/acl_xml2.h | 36 +++-- lib_acl/src/stdlib/iostuff/acl_read_wait.c | 16 +- lib_acl/src/stdlib/sys/acl_dll.c | 17 +- lib_acl/src/stdlib/sys/acl_sys_socket.c | 37 +++-- lib_acl/src/xml/acl_xml2_parse.c | 173 ++++++++++++++++++--- lib_acl/src/xml/acl_xml_parse.c | 111 +++++++++++-- lib_acl_cpp/changes.txt | 6 + lib_acl_cpp/include/acl_cpp/lib_acl.hpp | 1 + lib_acl_cpp/samples/xml/xml4/Makefile | 3 + lib_acl_cpp/samples/xml/xml4/cdata.xml | 14 ++ lib_acl_cpp/samples/xml/xml4/cdata2.xml | 69 ++++++++ lib_acl_cpp/samples/xml/xml4/main.cpp | 148 ++++++++++++++++++ lib_acl_cpp/samples/xml/xml4/stdafx.cpp | 4 + lib_acl_cpp/samples/xml/xml4/stdafx.h | 12 ++ lib_acl_cpp/samples/xml/xml4/valgrind.sh | 3 + lib_acl_cpp/src/db/db_mysql.cpp | 138 +++++++++++++--- lib_acl_cpp/src/stdlib/url_coder.cpp | 3 +- lib_acl_cpp/src/stdlib/zlib_stream.cpp | 22 +-- 21 files changed, 730 insertions(+), 123 deletions(-) create mode 100644 lib_acl_cpp/samples/xml/xml4/Makefile create mode 100644 lib_acl_cpp/samples/xml/xml4/cdata.xml create mode 100644 lib_acl_cpp/samples/xml/xml4/cdata2.xml create mode 100644 lib_acl_cpp/samples/xml/xml4/main.cpp create mode 100644 lib_acl_cpp/samples/xml/xml4/stdafx.cpp create mode 100644 lib_acl_cpp/samples/xml/xml4/stdafx.h create mode 100644 lib_acl_cpp/samples/xml/xml4/valgrind.sh diff --git a/lib_acl/changes.txt b/lib_acl/changes.txt index 2806c142e..73beb81c7 100644 --- a/lib_acl/changes.txt +++ b/lib_acl/changes.txt @@ -1,6 +1,9 @@ 修改历史列表: ------------------------------------------------------------------------ +516) 2015.12.9 +516.1) feature: acl_xml_parse.c / acl_xml2_parse.c can parse CDATA + 515) 2015.12.8 515.1) bugfix: acl_vstream.c 中当 read/write 接口被注入时,因为没有对应的 writev 注入方式,所以需要多次调用 write 来模拟 writev 过程 diff --git a/lib_acl/include/stdlib/acl_dll.h b/lib_acl/include/stdlib/acl_dll.h index cb4309c63..fb926a0ef 100644 --- a/lib_acl/include/stdlib/acl_dll.h +++ b/lib_acl/include/stdlib/acl_dll.h @@ -19,6 +19,7 @@ typedef struct ACL_DLL_ENV { ACL_API ACL_DLL_HANDLE acl_dlopen(const char *dlname); ACL_API void acl_dlclose(ACL_DLL_HANDLE handle); ACL_API ACL_DLL_FARPROC acl_dlsym(void *handle, const char *name); +ACL_API const char *acl_dlerror(void); #ifdef __cplusplus } diff --git a/lib_acl/include/xml/acl_xml.h b/lib_acl/include/xml/acl_xml.h index d01d43f52..817c1c228 100644 --- a/lib_acl/include/xml/acl_xml.h +++ b/lib_acl/include/xml/acl_xml.h @@ -53,6 +53,7 @@ struct ACL_XML_NODE { #define ACL_XML_F_META_EM (1 << 2) /**< only '!' flag */ #define ACL_XML_F_SELF_CL (1 << 3) /**< self closed flag */ #define ACL_XML_F_LEAF (1 << 4) /**< leaf node has no child node */ +#define ACL_XML_F_CDATA (1 << 5) /**< CDATA data */ /**< 是否是元数据 */ #define ACL_XML_F_META \ @@ -60,23 +61,26 @@ struct ACL_XML_NODE { #define ACL_XML_IS_COMMENT(x) (((x)->flag & ACL_XML_F_META_CM)) +#define ACL_XML_IS_CDATA(x) (((x)->flag & ACL_XML_F_CDATA)) + int status; /**< 状态机当前解析状态 */ -#define ACL_XML_S_NXT 0 /**< 下一个节点 */ -#define ACL_XML_S_LLT 1 /**< 左边 '<' */ -#define ACL_XML_S_LGT 2 /**< 右边 '>' */ -#define ACL_XML_S_LCH 3 /**< 左边 '<' 后第一个字节 */ -#define ACL_XML_S_LEM 4 /**< 左边 '<' 后的 '!' */ -#define ACL_XML_S_LTAG 5 /**< 左边的标签名 */ -#define ACL_XML_S_RLT 6 /**< 右边的 '<' */ -#define ACL_XML_S_RGT 7 /**< 右边的 '>' */ -#define ACL_XML_S_RTAG 8 /**< 右边的标签名 */ -#define ACL_XML_S_ATTR 9 /**< 标签属性名 */ -#define ACL_XML_S_AVAL 10 /**< 标签属性值 */ -#define ACL_XML_S_TXT 11 /**< 节点文本 */ -#define ACL_XML_S_MTAG 12 /**< 元数据标签 */ -#define ACL_XML_S_MTXT 13 /**< 元数据文本 */ -#define ACL_XML_S_MCMT 14 /**< 元数据注释 */ -#define ACL_XML_S_MEND 15 /**< 元数据结束 */ +#define ACL_XML_S_NXT 0 /**< 下一个节点 */ +#define ACL_XML_S_LLT 1 /**< 左边 '<' */ +#define ACL_XML_S_LGT 2 /**< 右边 '>' */ +#define ACL_XML_S_LCH 3 /**< 左边 '<' 后第一个字节 */ +#define ACL_XML_S_LEM 4 /**< 左边 '<' 后的 '!' */ +#define ACL_XML_S_LTAG 5 /**< 左边的标签名 */ +#define ACL_XML_S_RLT 6 /**< 右边的 '<' */ +#define ACL_XML_S_RGT 7 /**< 右边的 '>' */ +#define ACL_XML_S_RTAG 8 /**< 右边的标签名 */ +#define ACL_XML_S_ATTR 9 /**< 标签属性名 */ +#define ACL_XML_S_AVAL 10 /**< 标签属性值 */ +#define ACL_XML_S_TXT 11 /**< 节点文本 */ +#define ACL_XML_S_MTAG 12 /**< 元数据标签 */ +#define ACL_XML_S_MTXT 13 /**< 元数据文本 */ +#define ACL_XML_S_MCMT 14 /**< 元数据注释 */ +#define ACL_XML_S_MEND 15 /**< 元数据结束 */ +#define ACL_XML_S_CDATA 16 /**< CDATA 数据 */ /* public: for acl_iterator, 通过 acl_foreach 列出该节点的一级子节点 */ diff --git a/lib_acl/include/xml/acl_xml2.h b/lib_acl/include/xml/acl_xml2.h index 698d1d069..a38fb70c3 100644 --- a/lib_acl/include/xml/acl_xml2.h +++ b/lib_acl/include/xml/acl_xml2.h @@ -61,6 +61,7 @@ struct ACL_XML2_NODE { #define ACL_XML2_F_META_EM (1 << 2) /**< only '!' flag */ #define ACL_XML2_F_SELF_CL (1 << 3) /**< self closed flag */ #define ACL_XML2_F_LEAF (1 << 4) /**< leaf node has no child node */ +#define ACL_XML2_F_CDATA (1 << 5) /**< CDATA data */ /**< 是否是元数据 */ #define ACL_XML2_F_META \ @@ -68,23 +69,26 @@ struct ACL_XML2_NODE { #define ACL_XML2_IS_COMMENT(x) (((x)->flag & ACL_XML2_F_META_CM)) +#define ACL_XML2_IS_CDATA(x) (((x)->flag & ACL_XML2_F_CDATA)) + int status; /**< 状态机当前解析状态 */ -#define ACL_XML2_S_NXT 0 /**< 下一个节点 */ -#define ACL_XML2_S_LLT 1 /**< 左边 '<' */ -#define ACL_XML2_S_LGT 2 /**< 右边 '>' */ -#define ACL_XML2_S_LCH 3 /**< 左边 '<' 后第一个字节 */ -#define ACL_XML2_S_LEM 4 /**< 左边 '<' 后的 '!' */ -#define ACL_XML2_S_LTAG 5 /**< 左边的标签名 */ -#define ACL_XML2_S_RLT 6 /**< 右边的 '<' */ -#define ACL_XML2_S_RGT 7 /**< 右边的 '>' */ -#define ACL_XML2_S_RTAG 8 /**< 右边的标签名 */ -#define ACL_XML2_S_ATTR 9 /**< 标签属性名 */ -#define ACL_XML2_S_AVAL 10 /**< 标签属性值 */ -#define ACL_XML2_S_TXT 11 /**< 节点文本 */ -#define ACL_XML2_S_MTAG 12 /**< 元数据标签 */ -#define ACL_XML2_S_MTXT 13 /**< 元数据文本 */ -#define ACL_XML2_S_MCMT 14 /**< 元数据注释 */ -#define ACL_XML2_S_MEND 15 /**< 元数据结束 */ +#define ACL_XML2_S_NXT 0 /**< 下一个节点 */ +#define ACL_XML2_S_LLT 1 /**< 左边 '<' */ +#define ACL_XML2_S_LGT 2 /**< 右边 '>' */ +#define ACL_XML2_S_LCH 3 /**< 左边 '<' 后第一个字节 */ +#define ACL_XML2_S_LEM 4 /**< 左边 '<' 后的 '!' */ +#define ACL_XML2_S_LTAG 5 /**< 左边的标签名 */ +#define ACL_XML2_S_RLT 6 /**< 右边的 '<' */ +#define ACL_XML2_S_RGT 7 /**< 右边的 '>' */ +#define ACL_XML2_S_RTAG 8 /**< 右边的标签名 */ +#define ACL_XML2_S_ATTR 9 /**< 标签属性名 */ +#define ACL_XML2_S_AVAL 10 /**< 标签属性值 */ +#define ACL_XML2_S_TXT 11 /**< 节点文本 */ +#define ACL_XML2_S_MTAG 12 /**< 元数据标签 */ +#define ACL_XML2_S_MTXT 13 /**< 元数据文本 */ +#define ACL_XML2_S_MCMT 14 /**< 元数据注释 */ +#define ACL_XML2_S_MEND 15 /**< 元数据结束 */ +#define ACL_XML2_S_CDATA 16 /**< CDATA 数据 */ /* for acl_iterator, 通过 acl_foreach 列出该节点的一级子节点 */ diff --git a/lib_acl/src/stdlib/iostuff/acl_read_wait.c b/lib_acl/src/stdlib/iostuff/acl_read_wait.c index 5c50ffedf..7937a1ba1 100644 --- a/lib_acl/src/stdlib/iostuff/acl_read_wait.c +++ b/lib_acl/src/stdlib/iostuff/acl_read_wait.c @@ -90,14 +90,6 @@ int acl_read_wait(ACL_SOCKET fd, int timeout) return -1; } - if ((events[0].events & (EPOLLERR | EPOLLHUP)) != 0) - return -1; - - if ((events[0].events & EPOLLIN) == 0) { - acl_set_error(ACL_ETIMEDOUT); - return -1; - } - ee.events = 0; ee.data.u64 = 0; ee.data.fd = fd; @@ -107,6 +99,14 @@ int acl_read_wait(ACL_SOCKET fd, int timeout) return -1; } + if ((events[0].events & (EPOLLERR | EPOLLHUP)) != 0) + return -1; + + if ((events[0].events & EPOLLIN) == 0) { + acl_set_error(ACL_ETIMEDOUT); + return -1; + } + return 0; } diff --git a/lib_acl/src/stdlib/sys/acl_dll.c b/lib_acl/src/stdlib/sys/acl_dll.c index 4d5946433..1181f0c5d 100644 --- a/lib_acl/src/stdlib/sys/acl_dll.c +++ b/lib_acl/src/stdlib/sys/acl_dll.c @@ -25,13 +25,15 @@ ACL_DLL_HANDLE acl_dlopen(const char *dlname) else handle = dlopen(dlname, RTLD_GLOBAL | RTLD_NOW); # endif + if (handle != NULL) + dlerror(); /* clear any existing error */ #elif defined(ACL_WINDOWS) handle = LoadLibrary(dlname); #endif if (handle == NULL) acl_msg_error("%s(%d): open(%s) error(%s)", myname, __LINE__, dlname, acl_last_serror()); - return (handle); + return handle; } void acl_dlclose(ACL_DLL_HANDLE handle) @@ -46,9 +48,18 @@ void acl_dlclose(ACL_DLL_HANDLE handle) ACL_DLL_FARPROC acl_dlsym(void *handle, const char *name) { #ifdef ACL_UNIX - return (dlsym(handle, name)); + return dlsym(handle, name); #elif defined(ACL_WINDOWS) - return (GetProcAddress(handle, name)); + return GetProcAddress(handle, name); #endif } +const char *acl_dlerror(void) +{ +#ifdef ACL_UNIX + const char *ptr = dlerror(); + return ptr == NULL ? "" : ptr; +#elif defined(ACL_WINDOWS) + return acl_last_serror(); +#endif +} diff --git a/lib_acl/src/stdlib/sys/acl_sys_socket.c b/lib_acl/src/stdlib/sys/acl_sys_socket.c index e69ee45fb..ce38bc164 100644 --- a/lib_acl/src/stdlib/sys/acl_sys_socket.c +++ b/lib_acl/src/stdlib/sys/acl_sys_socket.c @@ -216,20 +216,35 @@ int acl_socket_close(ACL_SOCKET fd) return close(fd); } +static int __sys_read(ACL_SOCKET fd, void *buf, size_t size, int readable) +{ + (void) readable; + return read(fd, buf, size); +} + +static int __sys_socket_read(ACL_SOCKET fd, void *buf, size_t size, + int timeout, int sys_read_ready) +{ + int readable; + + if (sys_read_ready == 0 && timeout > 0) { + if (acl_read_wait(fd, timeout) < 0) { + errno = acl_last_error(); + return -1; + } + + readable = 1; + } else + readable = 0; + + return __sys_read(fd, buf, size, readable); +} + int acl_socket_read(ACL_SOCKET fd, void *buf, size_t size, int timeout, ACL_VSTREAM *fp, void *arg acl_unused) { - if (fp != NULL && fp->sys_read_ready) { - fp->sys_read_ready = 0; - timeout = 0; - } - - if (timeout > 0 && acl_read_wait(fd, timeout) < 0) { - errno = acl_last_error(); - return -1; - } - - return read(fd, buf, size); + return __sys_socket_read(fd, buf, size, timeout, + fp ? fp->sys_read_ready : 0); } int acl_socket_write(ACL_SOCKET fd, const void *buf, size_t size, diff --git a/lib_acl/src/xml/acl_xml2_parse.c b/lib_acl/src/xml/acl_xml2_parse.c index 170a0af30..dcb0f04ae 100644 --- a/lib_acl/src/xml/acl_xml2_parse.c +++ b/lib_acl/src/xml/acl_xml2_parse.c @@ -133,6 +133,131 @@ static const char *xml_parse_left_em(ACL_XML2 *xml, const char *data) return data; } +static const char *xml_parse_cdata(ACL_XML2 *xml, const char *data) +{ + ACL_XML2_NODE *curr_node = xml->curr_node; + int ch; + + while ((ch = *data) != 0) { + data++; + + if (ch == '>') { + if (curr_node->meta[0] == ']' + && curr_node->meta[1] == ']') + { + curr_node->status = ACL_XML2_S_MEND; + curr_node->text_size = + xml->ptr - curr_node->text; + + if (xml->len > MIN_LEN) { + *xml->ptr++ = 0; + xml->len--; + } + return data; + } + if (curr_node->meta[0] == ']') { + if (xml->len > MIN_LEN) { + *xml->ptr++ = curr_node->meta[0]; + xml->len--; + } + curr_node->meta[0] = 0; + } + if (curr_node->meta[1] == ']') { + if (xml->len > MIN_LEN) { + *xml->ptr++ = curr_node->meta[1]; + xml->len--; + } + curr_node->meta[1] = 0; + } + } else if (ch == ']') { + if (curr_node->meta[0] == ']') { + if (curr_node->meta[1] == ']') { + if (xml->len < MIN_LEN) + return data; + *xml->ptr++ = ']'; + xml->len--; + } else + curr_node->meta[1] = ']'; + } else if (curr_node->meta[1] == ']') { + curr_node->meta[0] = ']'; + curr_node->meta[1] = 0; + if (xml->len < MIN_LEN) + return data; + *xml->ptr++ = ']'; + xml->len--; + } else + curr_node->meta[0] = ']'; + } else if (curr_node->meta[0] == ']') { + if (xml->len < MIN_LEN) + return data; + *xml->ptr++ = ']'; + xml->len--; + curr_node->meta[0] = 0; + + if (curr_node->meta[1] == ']') { + if (xml->len < MIN_LEN) + return data; + *xml->ptr++ = ']'; + xml->len--; + curr_node->meta[1] = 0; + } + } else { + if (xml->len < MIN_LEN) + return data; + *xml->ptr++ = ch; + xml->len--; + } + } + + *xml->ptr = 0; + return data; +} +#define IS_CDATA(x) (*(x) == '[' \ + && (*(x + 1) == 'C' || *(x + 1) == 'c') \ + && (*(x + 2) == 'D' || *(x + 2) == 'd') \ + && (*(x + 3) == 'A' || *(x + 3) == 'a') \ + && (*(x + 4) == 'T' || *(x + 4) == 't') \ + && (*(x + 5) == 'A' || *(x + 5) == 't') \ + && *(x + 6) == '[') + +static void cdata_prepare(ACL_XML2 *xml, int last_ch) +{ + size_t cdata_len = sizeof("[CDATA[") - 1, len, max, i; + ACL_XML2_NODE *curr_node = xml->curr_node; + char *src, *dst; + + if (xml->len <= MIN_LEN || curr_node->ltag_size <= cdata_len) + return; + + /* compute the max bytes for data copying */ + max = xml->len - MIN_LEN; + len = curr_node->ltag_size - cdata_len; + if (len > max) + len = max; + + src = curr_node->ltag + cdata_len; /* src is at the end of ltag */ + curr_node->text = src + 1; /* one space for '\0' of ltag */ + + /* moving data reverse in the same memory won't override the data */ + + dst = src + len; /* one space after the data end */ + src = dst - 1; + xml->ptr = dst + 1; + xml->len -= len; + + for (i = 0; i < len; i++) + *dst-- = *src--; + + /* terminate the ltag string */ + curr_node->ltag_size = cdata_len; + curr_node->ltag[curr_node->ltag_size] = 0; + + if (xml->len < MIN_LEN) + return; + *xml->ptr++ = last_ch; + xml->len--; +} + static const char *xml_parse_meta_tag(ACL_XML2 *xml, const char *data) { int ch; @@ -148,11 +273,20 @@ static const char *xml_parse_meta_tag(ACL_XML2 *xml, const char *data) if (xml->len < MIN_LEN) return data; data++; - xml->len--; xml->curr_node->ltag_size = xml->ptr - xml->curr_node->ltag; - *xml->ptr++ = 0; - xml->curr_node->status = ACL_XML2_S_MTXT; + + if (IS_CDATA(xml->curr_node->ltag)) { + cdata_prepare(xml, ch); + xml->curr_node->status = ACL_XML2_S_CDATA; + xml->curr_node->flag |= ACL_XML2_F_CDATA; + } else { + if (xml->len < MIN_LEN) + return data; + *xml->ptr++ = 0; + xml->len--; + xml->curr_node->status = ACL_XML2_S_MTXT; + } break; } @@ -989,22 +1123,23 @@ static const char *xml_parse_right_gt(ACL_XML2 *xml, const char *data) } static struct XML_STATUS_MACHINE status_tab[] = { - { ACL_XML2_S_NXT, xml_parse_next_left_lt }, - { ACL_XML2_S_LLT, xml_parse_left_lt }, - { ACL_XML2_S_LGT, xml_parse_left_gt }, - { ACL_XML2_S_LCH, xml_parse_left_ch }, - { ACL_XML2_S_LEM, xml_parse_left_em }, - { ACL_XML2_S_LTAG, xml_parse_left_tag }, - { ACL_XML2_S_RLT, xml_parse_right_lt }, - { ACL_XML2_S_RGT, xml_parse_right_gt }, - { ACL_XML2_S_RTAG, xml_parse_right_tag }, - { ACL_XML2_S_ATTR, xml_parse_attr }, - { ACL_XML2_S_AVAL, xml_parse_attr_val }, - { ACL_XML2_S_TXT, xml_parse_text }, - { ACL_XML2_S_MTAG, xml_parse_meta_tag }, - { ACL_XML2_S_MTXT, xml_parse_meta_text }, - { ACL_XML2_S_MCMT, xml_parse_meta_comment }, - { ACL_XML2_S_MEND, xml_parse_meta_end }, + { ACL_XML2_S_NXT, xml_parse_next_left_lt }, + { ACL_XML2_S_LLT, xml_parse_left_lt }, + { ACL_XML2_S_LGT, xml_parse_left_gt }, + { ACL_XML2_S_LCH, xml_parse_left_ch }, + { ACL_XML2_S_LEM, xml_parse_left_em }, + { ACL_XML2_S_LTAG, xml_parse_left_tag }, + { ACL_XML2_S_RLT, xml_parse_right_lt }, + { ACL_XML2_S_RGT, xml_parse_right_gt }, + { ACL_XML2_S_RTAG, xml_parse_right_tag }, + { ACL_XML2_S_ATTR, xml_parse_attr }, + { ACL_XML2_S_AVAL, xml_parse_attr_val }, + { ACL_XML2_S_TXT, xml_parse_text }, + { ACL_XML2_S_MTAG, xml_parse_meta_tag }, + { ACL_XML2_S_MTXT, xml_parse_meta_text }, + { ACL_XML2_S_MCMT, xml_parse_meta_comment }, + { ACL_XML2_S_MEND, xml_parse_meta_end }, + { ACL_XML2_S_CDATA, xml_parse_cdata }, }; const char *acl_xml2_update(ACL_XML2 *xml, const char *data) diff --git a/lib_acl/src/xml/acl_xml_parse.c b/lib_acl/src/xml/acl_xml_parse.c index a611437c9..66d36b4c7 100644 --- a/lib_acl/src/xml/acl_xml_parse.c +++ b/lib_acl/src/xml/acl_xml_parse.c @@ -26,7 +26,11 @@ && (*(ptr + 1) == 'd' || *(ptr + 1) == 'D')) #define IS_QUOTE(x) ((x) == '\"' || (x) == '\'') +#if 1 #define IS_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n') +#else +#define IS_SPACE(c) ((c) == ' ' || (c) == '\t') +#endif #define SKIP_WHILE(cond, ptr) { while(*(ptr) && (cond)) (ptr)++; } #define SKIP_SPACE(ptr) { while(IS_SPACE(*(ptr))) (ptr)++; } @@ -122,6 +126,72 @@ static const char *xml_parse_left_em(ACL_XML *xml, const char *data) return data; } +static const char *xml_parse_cdata(ACL_XML *xml, const char *data) +{ + ACL_XML_NODE *curr_node = xml->curr_node; + int ch; + + while ((ch = *data) != 0) { + data++; + + if (ch == '>') { + if (curr_node->meta[0] == ']' + && curr_node->meta[1] == ']') + { + curr_node->status = ACL_XML_S_MEND; + ACL_VSTRING_TERMINATE(curr_node->text); + return data; + } + if (curr_node->meta[0]) + ADDCH(curr_node->text, curr_node->meta[0]); + curr_node->meta[0] = 0; + if (curr_node->meta[1]) + ADDCH(curr_node->text, curr_node->meta[1]); + curr_node->meta[1] = 0; + } else if (ch == ']') { + if (curr_node->meta[0] == ']') { + if (curr_node->meta[1] == ']') + ADDCH(curr_node->text, ']'); + else + curr_node->meta[1] = ']'; + } else if (curr_node->meta[1] == ']') { + curr_node->meta[0] = ']'; + curr_node->meta[1] = 0; + ADDCH(curr_node->text, ']'); + } else + curr_node->meta[0] = ']'; + } else if (curr_node->meta[0] == ']') { + ADDCH(curr_node->text, ']'); + curr_node->meta[0] = 0; + if (curr_node->meta[1] == ']') + ADDCH(curr_node->text, ']'); + curr_node->meta[1] = 0; + } else { + ADDCH(curr_node->text, ch); + } + } + + ACL_VSTRING_TERMINATE(curr_node->text); + return data; +} + +#define IS_CDATA(x) (*(x) == '[' \ + && (*(x + 1) == 'C' || *(x + 1) == 'c') \ + && (*(x + 2) == 'D' || *(x + 2) == 'd') \ + && (*(x + 3) == 'A' || *(x + 3) == 'a') \ + && (*(x + 4) == 'T' || *(x + 4) == 't') \ + && (*(x + 5) == 'A' || *(x + 5) == 't') \ + && *(x + 6) == '[') + +static void cdata_prepare(ACL_XML_NODE *curr_node) +{ + char *ptr = STR(curr_node->ltag) + sizeof("[CDATA[") - 1; + + acl_vstring_strcpy(curr_node->text, ptr); + ACL_VSTRING_AT_OFFSET(curr_node->ltag, sizeof("[CDATA[") - 1); + ACL_VSTRING_TERMINATE(curr_node->ltag); +} + static const char *xml_parse_meta_tag(ACL_XML *xml, const char *data) { int ch; @@ -129,7 +199,13 @@ static const char *xml_parse_meta_tag(ACL_XML *xml, const char *data) while ((ch = *data) != 0) { data++; if (IS_SPACE(ch) || ch == '>') { - xml->curr_node->status = ACL_XML_S_MTXT; + if (IS_CDATA(STR(xml->curr_node->ltag))) { + cdata_prepare(xml->curr_node); + ADDCH(xml->curr_node->text, ch); + xml->curr_node->status = ACL_XML_S_CDATA; + xml->curr_node->flag |= ACL_XML_F_CDATA; + } else + xml->curr_node->status = ACL_XML_S_MTXT; break; } ADDCH(xml->curr_node->ltag, ch); @@ -733,22 +809,23 @@ static const char *xml_parse_right_gt(ACL_XML *xml, const char *data) } static struct XML_STATUS_MACHINE status_tab[] = { - { ACL_XML_S_NXT, xml_parse_next_left_lt }, - { ACL_XML_S_LLT, xml_parse_left_lt }, - { ACL_XML_S_LGT, xml_parse_left_gt }, - { ACL_XML_S_LCH, xml_parse_left_ch }, - { ACL_XML_S_LEM, xml_parse_left_em }, - { ACL_XML_S_LTAG, xml_parse_left_tag }, - { ACL_XML_S_RLT, xml_parse_right_lt }, - { ACL_XML_S_RGT, xml_parse_right_gt }, - { ACL_XML_S_RTAG, xml_parse_right_tag }, - { ACL_XML_S_ATTR, xml_parse_attr }, - { ACL_XML_S_AVAL, xml_parse_attr_val }, - { ACL_XML_S_TXT, xml_parse_text }, - { ACL_XML_S_MTAG, xml_parse_meta_tag }, - { ACL_XML_S_MTXT, xml_parse_meta_text }, - { ACL_XML_S_MCMT, xml_parse_meta_comment }, - { ACL_XML_S_MEND, xml_parse_meta_end }, + { ACL_XML_S_NXT, xml_parse_next_left_lt }, + { ACL_XML_S_LLT, xml_parse_left_lt }, + { ACL_XML_S_LGT, xml_parse_left_gt }, + { ACL_XML_S_LCH, xml_parse_left_ch }, + { ACL_XML_S_LEM, xml_parse_left_em }, + { ACL_XML_S_LTAG, xml_parse_left_tag }, + { ACL_XML_S_RLT, xml_parse_right_lt }, + { ACL_XML_S_RGT, xml_parse_right_gt }, + { ACL_XML_S_RTAG, xml_parse_right_tag }, + { ACL_XML_S_ATTR, xml_parse_attr }, + { ACL_XML_S_AVAL, xml_parse_attr_val }, + { ACL_XML_S_TXT, xml_parse_text }, + { ACL_XML_S_MTAG, xml_parse_meta_tag }, + { ACL_XML_S_MTXT, xml_parse_meta_text }, + { ACL_XML_S_MCMT, xml_parse_meta_comment }, + { ACL_XML_S_MEND, xml_parse_meta_end }, + { ACL_XML_S_CDATA, xml_parse_cdata }, }; const char *acl_xml_update(ACL_XML *xml, const char *data) diff --git a/lib_acl_cpp/changes.txt b/lib_acl_cpp/changes.txt index d54b1a2e2..5b49bb5bd 100644 --- a/lib_acl_cpp/changes.txt +++ b/lib_acl_cpp/changes.txt @@ -1,6 +1,12 @@ 修改历史列表: ----------------------------------------------------------------------- +387) 2015.12.9 +387.1) bugfix: db_mysql 类中,在初始 mysql 连接时,因为 libmysqlclient 库内部 +会通过 mysql_thread_init 初始化每个线程的线程局部变量,但却不会在线程退出前自 +动释放这些线程局部变量,这在多线程环境下会造成内存泄露,因为在 db_mysql 类内部 +增加了线程退出前调用 mysql_thread_end 来释放这些线程局部变量 + 386) 2015.12.7 386.1) feature: xml_node 类中增加接口 detach 用于将一个 xml 节点从 xml 对象 树中分离 diff --git a/lib_acl_cpp/include/acl_cpp/lib_acl.hpp b/lib_acl_cpp/include/acl_cpp/lib_acl.hpp index 02ca024df..b21b7b369 100644 --- a/lib_acl_cpp/include/acl_cpp/lib_acl.hpp +++ b/lib_acl_cpp/include/acl_cpp/lib_acl.hpp @@ -18,6 +18,7 @@ #include "acl_cpp/stdlib/util.hpp" #include "acl_cpp/stdlib/xml.hpp" #include "acl_cpp/stdlib/xml1.hpp" +#include "acl_cpp/stdlib/xml2.hpp" #include "acl_cpp/stdlib/zlib_stream.hpp" #include "acl_cpp/stdlib/md5.hpp" #include "acl_cpp/stdlib/charset_conv.hpp" diff --git a/lib_acl_cpp/samples/xml/xml4/Makefile b/lib_acl_cpp/samples/xml/xml4/Makefile new file mode 100644 index 000000000..9950e1715 --- /dev/null +++ b/lib_acl_cpp/samples/xml/xml4/Makefile @@ -0,0 +1,3 @@ +base_path = ../../.. +PROG = xml +include ../../Makefile.in diff --git a/lib_acl_cpp/samples/xml/xml4/cdata.xml b/lib_acl_cpp/samples/xml/xml4/cdata.xml new file mode 100644 index 000000000..dde69f7b3 --- /dev/null +++ b/lib_acl_cpp/samples/xml/xml4/cdata.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/lib_acl_cpp/samples/xml/xml4/cdata2.xml b/lib_acl_cpp/samples/xml/xml4/cdata2.xml new file mode 100644 index 000000000..afb25960b --- /dev/null +++ b/lib_acl_cpp/samples/xml/xml4/cdata2.xml @@ -0,0 +1,69 @@ + + + diff --git a/lib_acl_cpp/samples/xml/xml4/main.cpp b/lib_acl_cpp/samples/xml/xml4/main.cpp new file mode 100644 index 000000000..f5df8b85e --- /dev/null +++ b/lib_acl_cpp/samples/xml/xml4/main.cpp @@ -0,0 +1,148 @@ +#include "stdafx.h" + +static void attr_print(const acl::xml_attr& attr, int depth) +{ + for (int i = 0; i < depth; i++) + printf("\t"); + + printf("%s=\"%s\"\r\n", attr.get_name(), attr.get_value()); +} + +static void node_attr_print(const acl::xml_node& node, int depth) +{ + const acl::xml_attr* attr = node.first_attr(); + while (attr) + { + attr_print(*attr, depth); + attr = node.next_attr(); + } +} + +static void xml_node_print(const acl::xml_node& node, int depth) +{ + for (int i = 0; i < depth; i++) + printf("\t"); + + printf("tag: %s\r\n", node.tag_name()); + + const char* txt = node.text(); + for (int i = 0; i < depth; i++) + printf("\t"); + printf("text: {%s}\r\n", txt ? txt : ""); + + node_attr_print(node, depth + 1); +} + +static void xml_node_walk(acl::xml_node& node, int depth) +{ + acl::xml_node* child = node.first_child(); + + while (child) + { + xml_node_print(*child, depth); + xml_node_walk(*child, depth + 1); + child = node.next_child(); + } +} + +static void test_build(void) +{ + acl::xml1 xml; + acl::xml_node& root = xml.get_root(); + + root.add_child("users", true) + .add_child("user", true) + .add_attr("name", "zsxxsz") + .add_attr("age", 100) + .get_parent() + .add_child("user", true) + .add_attr("name", "zsx1") + .add_attr("age", 102); + + acl::xml_node& node = xml.create_node("name", "value"); + (void) node; + + acl::string buf; + xml.build_xml(buf); + + printf("%s\r\n", buf.c_str()); + printf("-----------------------------------------------------\r\n"); + xml_node_walk(xml.get_root(), 0); +} + +static void test_parse(const char* filepath) +{ + acl::string buf; + if (acl::ifstream::load(filepath, &buf) == false) + { + printf("load %s error %s\r\n", filepath, acl::last_serror()); + return; + } + + acl::xml1 xml; + xml.update(buf); + //printf("------------- buf data print ----------------------\r\n"); + //printf("[%s]\r\n", buf.c_str()); + //printf("------------- xml data print-----------------------\r\n"); + //printf("[%s]\r\n", xml.to_string()); + printf("------------- xml node walk -----------------------\r\n"); + xml_node_walk(xml.get_root(), 0); +} + +static void test_parse_mmap(const char* filepath) +{ + acl::string buf; + if (acl::ifstream::load(filepath, &buf) == false) + { + printf("load %s error %s\r\n", filepath, acl::last_serror()); + return; + } + + const char* local_file = "./local.map"; + acl::xml2 xml(local_file, buf.size() * 2); + xml.update(buf.c_str()); + printf("------------- xml node walk -----------------------\r\n"); + xml_node_walk(xml.get_root(), 0); +} + +static void usage(const char* procname) +{ + printf("usage: %s -h[help] -f parse_file -m[use mmap xml]\r\n", procname); +} + +int main(int argc, char* argv[]) +{ + int ch; + acl::string path; + bool use_mmap = false; + + while ((ch = getopt(argc, argv, "hf:m")) > 0) + { + switch (ch) + { + case 'h': + usage(argv[0]); + return 0; + case 'f': + path = optarg; + break; + case 'm': + use_mmap = true; + break; + default: + break; + } + } + + if (path.empty()) + test_build(); + else + { + if (use_mmap) + test_parse_mmap(path); + else + test_parse(path); + } + + return 0; +} diff --git a/lib_acl_cpp/samples/xml/xml4/stdafx.cpp b/lib_acl_cpp/samples/xml/xml4/stdafx.cpp new file mode 100644 index 000000000..a7dbd1b53 --- /dev/null +++ b/lib_acl_cpp/samples/xml/xml4/stdafx.cpp @@ -0,0 +1,4 @@ +#include "stdafx.h" + +// TODO: 在 STDAFX.H 中 +// 引用任何所需的附加头文件,而不是在此文件中引用 diff --git a/lib_acl_cpp/samples/xml/xml4/stdafx.h b/lib_acl_cpp/samples/xml/xml4/stdafx.h new file mode 100644 index 000000000..fe77279be --- /dev/null +++ b/lib_acl_cpp/samples/xml/xml4/stdafx.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +// TODO: 在此处引用程序需要的其他头文件 + +#include "lib_acl.h" +#include "acl_cpp/lib_acl.hpp" + +#if !defined(_WIN32) && !defined(_WIN64) +#include +#endif diff --git a/lib_acl_cpp/samples/xml/xml4/valgrind.sh b/lib_acl_cpp/samples/xml/xml4/valgrind.sh new file mode 100644 index 000000000..3a9d3bb09 --- /dev/null +++ b/lib_acl_cpp/samples/xml/xml4/valgrind.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +valgrind --tool=memcheck --leak-check=yes -v ./xml diff --git a/lib_acl_cpp/src/db/db_mysql.cpp b/lib_acl_cpp/src/db/db_mysql.cpp index e2224b12c..3b394f6b5 100644 --- a/lib_acl_cpp/src/db/db_mysql.cpp +++ b/lib_acl_cpp/src/db/db_mysql.cpp @@ -44,6 +44,10 @@ typedef void (STDCALL *mysql_free_result_fn)(MYSQL_RES*); typedef my_ulonglong (STDCALL *mysql_affected_rows_fn)(MYSQL*); typedef int (STDCALL *mysql_set_character_set_fn)(MYSQL*, const char*); typedef const char* (STDCALL *mysql_character_set_name_fn)(MYSQL*); +typedef void (STDCALL *mysql_thread_init_fn)(void); +typedef void (STDCALL *mysql_thread_end_fn)(void); +typedef void (STDCALL *mysql_server_init_fn)(void); +typedef void (STDCALL *mysql_server_end_fn)(void); static mysql_libversion_fn __mysql_libversion = NULL; static mysql_client_info_fn __mysql_client_info = NULL; @@ -64,6 +68,10 @@ static mysql_free_result_fn __mysql_free_result = NULL; static mysql_affected_rows_fn __mysql_affected_rows = NULL; static mysql_set_character_set_fn __mysql_set_character_set = NULL; static mysql_character_set_name_fn __mysql_character_set_name = NULL; +static mysql_thread_init_fn __mysql_thread_init = NULL; +static mysql_thread_end_fn __mysql_thread_end = NULL; +static mysql_server_init_fn __mysql_server_init = NULL; +static mysql_server_end_fn __mysql_server_end = NULL; static acl_pthread_once_t __mysql_once = ACL_PTHREAD_ONCE_INIT; static ACL_DLL_HANDLE __mysql_dll = NULL; @@ -76,6 +84,12 @@ static void __mysql_dll_unload(void) { if (__mysql_dll != NULL) { + if (__mysql_server_end != NULL) + { + __mysql_server_end(); + __mysql_server_end = NULL; + } + acl_dlclose(__mysql_dll); __mysql_dll = NULL; logger("%s unload ok", __mysql_path.c_str()); @@ -103,7 +117,7 @@ static void __mysql_dll_load(void) __mysql_dll = acl_dlopen(path); if (__mysql_dll == NULL) - logger_fatal("load %s error: %s", path, acl_last_serror()); + logger_fatal("load %s error: %s", path, acl_dlerror()); // 记录动态库路径,以便于在动态库卸载时输出库路径名 __mysql_path = path; @@ -112,114 +126,139 @@ static void __mysql_dll_load(void) acl_dlsym(__mysql_dll, "mysql_get_client_version"); if (__mysql_libversion == NULL) logger_fatal("load mysql_get_client_version from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_client_info = (mysql_client_info_fn) acl_dlsym(__mysql_dll, "mysql_get_client_info"); if (__mysql_client_info == NULL) logger_fatal("load mysql_get_client_info from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_init = (mysql_init_fn) acl_dlsym(__mysql_dll, "mysql_init"); if (__mysql_init == NULL) logger_fatal("load mysql_init from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_open = (mysql_open_fn) acl_dlsym(__mysql_dll, "mysql_real_connect"); if (__mysql_open == NULL) logger_fatal("load mysql_real_connect from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_close = (mysql_close_fn) acl_dlsym(__mysql_dll, "mysql_close"); if (__mysql_close == NULL) logger_fatal("load mysql_close from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_options = (mysql_options_fn) acl_dlsym(__mysql_dll, "mysql_options"); if (__mysql_options == NULL) logger_fatal("load mysql_options from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_autocommit = (mysql_autocommit_fn) acl_dlsym(__mysql_dll, "mysql_autocommit"); if (__mysql_autocommit == NULL) logger_fatal("load mysql_autocommit from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_errno = (mysql_errno_fn) acl_dlsym(__mysql_dll, "mysql_errno"); if (__mysql_errno == NULL) logger_fatal("load mysql_errno from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_error = (mysql_error_fn) acl_dlsym(__mysql_dll, "mysql_error"); if (__mysql_error == NULL) logger_fatal("load mysql_error from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_query = (mysql_query_fn) acl_dlsym(__mysql_dll, "mysql_query"); if (__mysql_query == NULL) logger_fatal("load mysql_query from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_num_fields = (mysql_num_fields_fn) acl_dlsym(__mysql_dll, "mysql_num_fields"); if (__mysql_num_fields == NULL) logger_fatal("load mysql_num_fields from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_fetch_fields = (mysql_fetch_fields_fn) acl_dlsym(__mysql_dll, "mysql_fetch_fields"); if (__mysql_fetch_fields == NULL) logger_fatal("load mysql_fetch_fields from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_fetch_row = (mysql_fetch_row_fn) acl_dlsym(__mysql_dll, "mysql_fetch_row"); if (__mysql_fetch_row == NULL) logger_fatal("load mysql_fetch_row from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_store_result = (mysql_store_result_fn) acl_dlsym(__mysql_dll, "mysql_store_result"); if (__mysql_store_result == NULL) logger_fatal("load mysql_store_result from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_num_rows = (mysql_num_rows_fn) acl_dlsym(__mysql_dll, "mysql_num_rows"); if (__mysql_num_rows == NULL) logger_fatal("load mysql_num_rows from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_free_result = (mysql_free_result_fn) acl_dlsym(__mysql_dll, "mysql_free_result"); if (__mysql_free_result == NULL) logger_fatal("load mysql_free_result from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_affected_rows = (mysql_affected_rows_fn) acl_dlsym(__mysql_dll, "mysql_affected_rows"); if (__mysql_affected_rows == NULL) logger_fatal("load mysql_affected_rows from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_set_character_set = (mysql_set_character_set_fn) acl_dlsym(__mysql_dll, "mysql_set_character_set"); if (__mysql_affected_rows == NULL) logger_fatal("load mysql_set_character_set_fn %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __mysql_character_set_name = (mysql_character_set_name_fn) acl_dlsym(__mysql_dll, "mysql_character_set_name"); if (__mysql_affected_rows == NULL) logger_fatal("load mysql_character_set_name from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); + + __mysql_thread_init = (mysql_thread_init_fn) + acl_dlsym(__mysql_dll, "mysql_thread_init"); + if (__mysql_thread_init == NULL) + logger_warn("load mysql_thread_init from %s error: %s", + path, acl_dlerror()); + + __mysql_thread_end = (mysql_thread_end_fn) + acl_dlsym(__mysql_dll, "mysql_thread_end"); + if (__mysql_thread_end == NULL) + logger_warn("load mysql_thread_end from %s error: %s", + path, acl_dlerror()); + + __mysql_server_init = (mysql_server_init_fn) + acl_dlsym(__mysql_dll, "mysql_server_init"); + if (__mysql_server_init == NULL) + logger_warn("load mysql_server_init from %s error: %s", + path, acl_dlerror()); + + __mysql_thread_end(); + __mysql_server_end = (mysql_server_end_fn) + acl_dlsym(__mysql_dll, "mysql_server_end"); + if (__mysql_server_end == NULL) + logger_warn("load mysql_server_end from %s error: %s", + path, acl_dlerror()); logger("%s loaded!", path); atexit(__mysql_dll_unload); @@ -245,6 +284,10 @@ static void __mysql_dll_load(void) # define __mysql_affected_rows mysql_affected_rows # define __mysql_set_character_set mysql_set_character_set # define __mysql_character_set_name mysql_character_set_name +# define __mysql_thread_init mysql_thread_init +# define __mysql_thread_end mysql_thread_end +# define __mysql_thread_init mysql_thread_init +# define __mysql_server_end mysql_server_end # endif @@ -401,6 +444,37 @@ const char* db_mysql::get_error() const return "mysql not opened yet!"; } +static acl_pthread_key_t __thread_key; + +static void thread_free_dummy(void* ctx) +{ + if ((unsigned long) acl_pthread_self() != acl_main_thread_self()) + acl_myfree(ctx); + + if (__mysql_thread_end) + __mysql_thread_end(); +} + +static int* __main_dummy = NULL; +static void main_free_dummy(void) +{ + if (__main_dummy) + { + acl_myfree(__main_dummy); + __main_dummy = NULL; + } + + if (__mysql_thread_end) + __mysql_thread_end(); +} + +static acl_pthread_once_t __thread_once_control = ACL_PTHREAD_ONCE_INIT; + +static void thread_once(void) +{ + acl_assert(!acl_pthread_key_create(&__thread_key, thread_free_dummy)); +} + bool db_mysql::dbopen(const char* charset /* = NULL */) { if (conn_) @@ -436,6 +510,27 @@ bool db_mysql::dbopen(const char* charset /* = NULL */) db_port = 0; } + int* dummy; + + if (acl_pthread_once(&__thread_once_control, thread_once) != 0) + logger_error("call thread_once error: %s", acl_last_serror()); + else if (!(dummy = (int*) acl_pthread_getspecific(__thread_key))) + { + dummy = (int*) acl_mymalloc(sizeof(int)); + *dummy = 1; + acl_assert(!acl_pthread_setspecific(__thread_key, dummy)); + + if (__mysql_thread_init != NULL) + __mysql_thread_init(); + + if ((unsigned long) acl_pthread_self() + == acl_main_thread_self()) + { + __main_dummy = dummy; + atexit(main_free_dummy); + } + } + conn_ = __mysql_init(NULL); if (conn_ == NULL) { @@ -482,7 +577,8 @@ bool db_mysql::dbopen(const char* charset /* = NULL */) logger_error("connect mysql error(%s), db_host=%s, db_port=%d," " db_unix=%s, db_name=%s, db_user=%s, db_pass=%s", __mysql_error(conn_), db_host ? db_host : "null", db_port, - db_unix ? db_unix : "null", dbname_, dbuser_, dbpass_); + db_unix ? db_unix : "null", dbname_, dbuser_, + dbpass_ ? dbpass_ : "null"); __mysql_close(conn_); conn_ = NULL; diff --git a/lib_acl_cpp/src/stdlib/url_coder.cpp b/lib_acl_cpp/src/stdlib/url_coder.cpp index 35cbd5a21..f20098cde 100644 --- a/lib_acl_cpp/src/stdlib/url_coder.cpp +++ b/lib_acl_cpp/src/stdlib/url_coder.cpp @@ -124,7 +124,8 @@ url_coder& url_coder::set(const char* name, const char* value, { if (name == NULL || *name == 0 || value == NULL || *value == 0) { - logger_error("invalid input"); + logger_error("invalid input: name: [%s], value: [%s]", + name ? name : "null", value ? value : "null"); return *this; } diff --git a/lib_acl_cpp/src/stdlib/zlib_stream.cpp b/lib_acl_cpp/src/stdlib/zlib_stream.cpp index 0a72e1d61..eb1724d77 100644 --- a/lib_acl_cpp/src/stdlib/zlib_stream.cpp +++ b/lib_acl_cpp/src/stdlib/zlib_stream.cpp @@ -72,7 +72,7 @@ static void __zlib_dll_load(void) __zlib_dll = acl_dlopen(path); if (__zlib_dll == NULL) - logger_fatal("load %s error: %s", path, acl_last_serror()); + logger_fatal("load %s error: %s", path, acl_dlerror()); // 记录动态库路径,以便于在动态库卸载时输出库路径名 __zlib_path = path; @@ -80,52 +80,52 @@ static void __zlib_dll_load(void) //__deflateInit = (deflateInit_fn) acl_dlsym(__zlib_dll, "deflateInit_"); //if (__deflateInit == NULL) // logger_fatal("load deflateInit from %s error: %s", - // path, acl_last_serror()); + // path, acl_dlerror()); __deflateInit2 = (deflateInit2_fn) acl_dlsym(__zlib_dll, "deflateInit2_"); if (__deflateInit2 == NULL) logger_fatal("load deflateInit from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __deflate = (deflate_fn) acl_dlsym(__zlib_dll, "deflate"); if (__deflate == NULL) logger_fatal("load deflate from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __deflateReset = (deflateReset_fn) acl_dlsym(__zlib_dll, "deflateReset"); if (__deflateReset == NULL) logger_fatal("load deflateReset from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __deflateEnd = (deflateEnd_fn) acl_dlsym(__zlib_dll, "deflateEnd"); if (__deflateEnd == NULL) logger_fatal("load deflateEnd from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __inflateInit2 = (inflateInit2_fn) acl_dlsym(__zlib_dll, "inflateInit2_"); if (__inflateInit2 == NULL) logger_fatal("load inflateInit from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __inflate = (inflate_fn) acl_dlsym(__zlib_dll, "inflate"); if (__inflate == NULL) logger_fatal("load inflate from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __inflateReset = (inflateReset_fn) acl_dlsym(__zlib_dll, "inflateReset"); if (__inflateReset == NULL) logger_fatal("load inflateReset from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __inflateEnd = (inflateEnd_fn) acl_dlsym(__zlib_dll, "inflateEnd"); if (__inflateEnd == NULL) logger_fatal("load inflateEnd from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); __crc32 = (crc32_fn) acl_dlsym(__zlib_dll, "crc32"); if (__crc32 == NULL) logger_fatal("load __crc32 from %s error: %s", - path, acl_last_serror()); + path, acl_dlerror()); logger("%s loaded", path); atexit(__zlib_dll_unload);