版权声明:本文根据DragonKing牛,E-Mail:wzhah@263.NET发布在https://openssl.126.com的系列文章整理修改而成(这个网站已经不能访问了),我自己所做的工作主要是针对新的1.0.2版本进行验证,修改错别字,和错误,重新排版,以及整理分类,配图。 未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处,这是对原创者的起码的尊重!!!
1 概述
程序设计时,一般通过函数的返回值来判断是否调用成功。设计良好的函数以及好的错误处理能帮助调用者快速找到错误原因。错误处理应该尽可能多的包含各种信息,包括:
- 错误码;
- 出错文件以及行号;
- 错误原因;
- 出错函数;
- 出错库;
- 出错模块与类别信息;
- 错误堆栈信息等。
- 出错信息最好能支持多种输出。可以是输出在标准输出上,也可以是文件等形式。
2 相关数据结构
2.1 错误代码
openssl中,通过unsigned long类型来存放错误信息。它包含三部分内容:库代码、函数代码以及错误原因代码。其中,库代码在openssl/err.h中定义,比如err.h中为库定义如下库代码:
/* library */
# define ERR_LIB_NONE 1
# define ERR_LIB_SYS 2
# define ERR_LIB_BN 3
# define ERR_LIB_RSA 4
# define ERR_LIB_DH 5
# define ERR_LIB_EVP 6
# define ERR_LIB_BUF 7
# define ERR_LIB_OBJ 8
# define ERR_LIB_PEM 9
# define ERR_LIB_DSA 10
# define ERR_LIB_X509 11
/* #define ERR_LIB_METH 12 */
# define ERR_LIB_ASN1 13
# define ERR_LIB_CONF 14
# define ERR_LIB_CRYPTO 15
# define ERR_LIB_EC 16
# define ERR_LIB_SSL 20
/* #define ERR_LIB_SSL23 21 */
/* #define ERR_LIB_SSL2 22 */
/* #define ERR_LIB_SSL3 23 */
/* #define ERR_LIB_RSAREF 30 */
/* #define ERR_LIB_PROXY 31 */
# define ERR_LIB_BIO 32
# define ERR_LIB_PKCS7 33
# define ERR_LIB_X509V3 34
# define ERR_LIB_PKCS12 35
# define ERR_LIB_RAND 36
# define ERR_LIB_DSO 37
# define ERR_LIB_ENGINE 38
# define ERR_LIB_OCSP 39
# define ERR_LIB_UI 40
# define ERR_LIB_COMP 41
# define ERR_LIB_ECDSA 42
# define ERR_LIB_ECDH 43
# define ERR_LIB_STORE 44
# define ERR_LIB_FIPS 45
# define ERR_LIB_CMS 46
# define ERR_LIB_TS 47
# define ERR_LIB_HMAC 48
/* # define ERR_LIB_JPAKE 49 */
# define ERR_LIB_CT 50
# define ERR_LIB_ASYNC 51
# define ERR_LIB_KDF 52
# define ERR_LIB_USER 128
函数代码以及错误原因代码由各个功能模块定义(同类代码不能与其他的重复,也不能超过一定的大小)。如:openssl/bio.h中定义了如下函数和错误原因代号:
/* Error codes for the BIO functions. */
/* Function codes. */
# define BIO_F_ACPT_STATE 100
# define BIO_F_ADDR_STRINGS 134
# define BIO_F_BIO_ACCEPT 101
# define BIO_F_BIO_ACCEPT_EX 137
# define BIO_F_BIO_ADDR_NEW 144
# define BIO_F_BIO_CALLBACK_CTRL 131
# define BIO_F_BIO_CONNECT 138
# define BIO_F_BIO_CTRL 103
# define BIO_F_BIO_GETS 104
# define BIO_F_BIO_GET_HOST_IP 106
# define BIO_F_BIO_GET_NEW_INDEX 102
# define BIO_F_BIO_GET_PORT 107
# define BIO_F_BIO_LISTEN 139
# define BIO_F_BIO_LOOKUP 135
# define BIO_F_BIO_MAKE_PAIR 121
# define BIO_F_BIO_NEW 108
# define BIO_F_BIO_NEW_FILE 109
# define BIO_F_BIO_NEW_MEM_BUF 126
# define BIO_F_BIO_NREAD 123
# define BIO_F_BIO_NREAD0 124
# define BIO_F_BIO_NWRITE 125
# define BIO_F_BIO_NWRITE0 122
# define BIO_F_BIO_PARSE_HOSTSERV 136
# define BIO_F_BIO_PUTS 110
# define BIO_F_BIO_READ 111
# define BIO_F_BIO_SOCKET 140
# define BIO_F_BIO_SOCKET_NBIO 142
# define BIO_F_BIO_SOCK_INFO 141
# define BIO_F_BIO_SOCK_INIT 112
# define BIO_F_BIO_WRITE 113
# define BIO_F_BUFFER_CTRL 114
# define BIO_F_CONN_CTRL 127
# define BIO_F_CONN_STATE 115
# define BIO_F_DGRAM_SCTP_READ 132
# define BIO_F_DGRAM_SCTP_WRITE 133
# define BIO_F_FILE_CTRL 116
# define BIO_F_FILE_READ 130
# define BIO_F_LINEBUFFER_CTRL 129
# define BIO_F_MEM_WRITE 117
# define BIO_F_SSL_NEW 118
/* Reason codes. */
# define BIO_R_ACCEPT_ERROR 100
# define BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET 141
# define BIO_R_AMBIGUOUS_HOST_OR_SERVICE 129
# define BIO_R_BAD_FOPEN_MODE 101
# define BIO_R_BROKEN_PIPE 124
# define BIO_R_CONNECT_ERROR 103
# define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107
# define BIO_R_GETSOCKNAME_ERROR 132
# define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS 133
# define BIO_R_GETTING_SOCKTYPE 134
# define BIO_R_INVALID_ARGUMENT 125
# define BIO_R_INVALID_SOCKET 135
# define BIO_R_IN_USE 123
# define BIO_R_LISTEN_V6_ONLY 136
# define BIO_R_LOOKUP_RETURNED_NOTHING 142
# define BIO_R_MALFORMED_HOST_OR_SERVICE 130
# define BIO_R_NBIO_CONNECT_ERROR 110
# define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143
# define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
# define BIO_R_NO_PORT_DEFINED 113
# define BIO_R_NO_SUCH_FILE 128
# define BIO_R_NULL_PARAMETER 115
# define BIO_R_UNABLE_TO_BIND_SOCKET 117
# define BIO_R_UNABLE_TO_CREATE_SOCKET 118
# define BIO_R_UNABLE_TO_KEEPALIVE 137
# define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
# define BIO_R_UNABLE_TO_NODELAY 138
# define BIO_R_UNABLE_TO_REUSEADDR 139
# define BIO_R_UNAVAILABLE_IP_FAMILY 145
# define BIO_R_UNINITIALIZED 120
# define BIO_R_UNKNOWN_INFO_TYPE 140
# define BIO_R_UNSUPPORTED_IP_FAMILY 146
# define BIO_R_UNSUPPORTED_METHOD 121
# define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131
# define BIO_R_WRITE_TO_READ_ONLY_BIO 126
# define BIO_R_WSASTARTUP 122
错误代码通过上述三部分通过计算得到,并且根据此信息能提取各个代码。计算函数在err.h中定义如下:
/*由库代码,函数代码,原因代码计算错误代码*/
# define ERR_PACK(l,f,r) (
(((unsigned int)(l) & 0x0FF) << 24L) |
(((unsigned int)(f) & 0xFFF) << 12L) |
(((unsigned int)(r) & 0xFFF) )
)
/*由错误代码计算库代码,函数代码,原因代码*/
# define ERR_GET_LIB(l) (int)(((l) >> 24L) & 0x0FFL)
# define ERR_GET_FUNC(l) (int)(((l) >> 12L) & 0xFFFL)
# define ERR_GET_REASON(l) (int)( (l) & 0xFFFL)
# define ERR_FATAL_ERROR(l) (int)( (l) & ERR_R_FATAL) //致命错误
可以看出,库的个数不能大于255(0xff),函数个数和错误原因不能大于4095(0xfff)。
2.2 基本数据结构
主要数据结构有两个,定义在err.h中。
2.2.1 ERR_STRING_DATA
typedef struct ERR_string_data_st
{
unsigned long error; //错误码
const char *string; //string用来存放文本信息,可以是函数名也可以是错误原因。
} ERR_STRING_DATA;
该数据结构的内容由各个功能模块来设置。其中,error用来存放错误信息(由库代码、函数代码以及错误原因代码计算得来),string用来存放文本信息,可以是函数名也可以是错误原因。以crypto/bio/bio_err.c为例,它定义了两个全局表,分别用来存放函数信息和错误信息:
# define ERR_FUNC(func) ERR_PACK(ERR_LIB_BIO,func,0)
# define ERR_REASON(reason) ERR_PACK(ERR_LIB_BIO,0,reason)
static ERR_STRING_DATA BIO_str_functs[] =
{
{ERR_FUNC(BIO_F_ACPT_STATE), "acpt_state"},
{ERR_FUNC(BIO_F_ADDR_STRINGS), "addr_strings"},
{ERR_FUNC(BIO_F_BIO_ACCEPT), "BIO_accept"},
{ERR_FUNC(BIO_F_BIO_ACCEPT_EX), "BIO_accept_ex"},
{ERR_FUNC(BIO_F_BIO_ADDR_NEW), "BIO_ADDR_new"},
{ERR_FUNC(BIO_F_BIO_CALLBACK_CTRL), "BIO_callback_ctrl"},
{ERR_FUNC(BIO_F_BIO_CONNECT), "BIO_connect"},
{ERR_FUNC(BIO_F_BIO_CTRL), "BIO_ctrl"},
{ERR_FUNC(BIO_F_BIO_GETS), "BIO_gets"},
{ERR_FUNC(BIO_F_BIO_GET_HOST_IP), "BIO_get_host_ip"},
{ERR_FUNC(BIO_F_BIO_GET_NEW_INDEX), "BIO_get_new_index"},
{ERR_FUNC(BIO_F_BIO_GET_PORT), "BIO_get_port"},
{ERR_FUNC(BIO_F_BIO_LISTEN), "BIO_listen"},
{ERR_FUNC(BIO_F_BIO_LOOKUP), "BIO_lookup"},
{ERR_FUNC(BIO_F_BIO_MAKE_PAIR), "bio_make_pair"},
{ERR_FUNC(BIO_F_BIO_NEW), "BIO_new"},
{ERR_FUNC(BIO_F_BIO_NEW_FILE), "BIO_new_file"},
{ERR_FUNC(BIO_F_BIO_NEW_MEM_BUF), "BIO_new_mem_buf"},
{ERR_FUNC(BIO_F_BIO_NREAD), "BIO_nread"},
{ERR_FUNC(BIO_F_BIO_NREAD0), "BIO_nread0"},
{ERR_FUNC(BIO_F_BIO_NWRITE), "BIO_nwrite"},
{ERR_FUNC(BIO_F_BIO_NWRITE0), "BIO_nwrite0"},
{ERR_FUNC(BIO_F_BIO_PARSE_HOSTSERV), "BIO_parse_hostserv"},
{ERR_FUNC(BIO_F_BIO_PUTS), "BIO_puts"},
{ERR_FUNC(BIO_F_BIO_READ), "BIO_read"},
{ERR_FUNC(BIO_F_BIO_SOCKET), "BIO_socket"},
{ERR_FUNC(BIO_F_BIO_SOCKET_NBIO), "BIO_socket_nbio"},
{ERR_FUNC(BIO_F_BIO_SOCK_INFO), "BIO_sock_info"},
{ERR_FUNC(BIO_F_BIO_SOCK_INIT), "BIO_sock_init"},
{ERR_FUNC(BIO_F_BIO_WRITE), "BIO_write"},
{ERR_FUNC(BIO_F_BUFFER_CTRL), "buffer_ctrl"},
{ERR_FUNC(BIO_F_CONN_CTRL), "conn_ctrl"},
{ERR_FUNC(BIO_F_CONN_STATE), "conn_state"},
{ERR_FUNC(BIO_F_DGRAM_SCTP_READ), "dgram_sctp_read"},
{ERR_FUNC(BIO_F_DGRAM_SCTP_WRITE), "dgram_sctp_write"},
{ERR_FUNC(BIO_F_FILE_CTRL), "file_ctrl"},
{ERR_FUNC(BIO_F_FILE_READ), "file_read"},
{ERR_FUNC(BIO_F_LINEBUFFER_CTRL), "linebuffer_ctrl"},
{ERR_FUNC(BIO_F_MEM_WRITE), "mem_write"},
{ERR_FUNC(BIO_F_SSL_NEW), "SSL_new"},
{0, NULL}
};
static ERR_STRING_DATA BIO_str_reasons[] =
{
{ERR_REASON(BIO_R_ACCEPT_ERROR), "accept error"},
{ERR_REASON(BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET),"addrinfo addr is not af inet"},
{ERR_REASON(BIO_R_AMBIGUOUS_HOST_OR_SERVICE),"ambiguous host or service"},
{ERR_REASON(BIO_R_BAD_FOPEN_MODE), "bad fopen mode"},
{ERR_REASON(BIO_R_BROKEN_PIPE), "broken pipe"},
{ERR_REASON(BIO_R_CONNECT_ERROR), "connect error"},
{ERR_REASON(BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET),"gethostbyname addr is not af inet"},
{ERR_REASON(BIO_R_GETSOCKNAME_ERROR), "getsockname error"},
{ERR_REASON(BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS),"getsockname truncated address"},
{ERR_REASON(BIO_R_GETTING_SOCKTYPE), "getting socktype"},
{ERR_REASON(BIO_R_INVALID_ARGUMENT), "invalid argument"},
{ERR_REASON(BIO_R_INVALID_SOCKET), "invalid socket"},
{ERR_REASON(BIO_R_IN_USE), "in use"},
{ERR_REASON(BIO_R_LISTEN_V6_ONLY), "listen v6 only"},
{ERR_REASON(BIO_R_LOOKUP_RETURNED_NOTHING), "lookup returned nothing"},
{ERR_REASON(BIO_R_MALFORMED_HOST_OR_SERVICE), "malformed host or service"},
{ERR_REASON(BIO_R_NBIO_CONNECT_ERROR), "nbio connect error"},
{ERR_REASON(BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED),"no accept addr or service specified"},
{ERR_REASON(BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED), "no hostname or service specified"},
{ERR_REASON(BIO_R_NO_PORT_DEFINED), "no port defined"},
{ERR_REASON(BIO_R_NO_SUCH_FILE), "no such file"},
{ERR_REASON(BIO_R_NULL_PARAMETER), "null parameter"},
{ERR_REASON(BIO_R_UNABLE_TO_BIND_SOCKET), "unable to bind socket"},
{ERR_REASON(BIO_R_UNABLE_TO_CREATE_SOCKET), "unable to create socket"},
{ERR_REASON(BIO_R_UNABLE_TO_KEEPALIVE), "unable to keepalive"},
{ERR_REASON(BIO_R_UNABLE_TO_LISTEN_SOCKET), "unable to listen socket"},
{ERR_REASON(BIO_R_UNABLE_TO_NODELAY), "unable to nodelay"},
{ERR_REASON(BIO_R_UNABLE_TO_REUSEADDR), "unable to reuseaddr"},
{ERR_REASON(BIO_R_UNAVAILABLE_IP_FAMILY), "unavailable ip family"},
{ERR_REASON(BIO_R_UNINITIALIZED), "uninitialized"},
{ERR_REASON(BIO_R_UNKNOWN_INFO_TYPE), "unknown info type"},
{ERR_REASON(BIO_R_UNSUPPORTED_IP_FAMILY), "unsupported ip family"},
{ERR_REASON(BIO_R_UNSUPPORTED_METHOD), "unsupported method"},
{ERR_REASON(BIO_R_UNSUPPORTED_PROTOCOL_FAMILY),"unsupported protocol family"},
{ERR_REASON(BIO_R_WRITE_TO_READ_ONLY_BIO), "write to read only BIO"},
{ERR_REASON(BIO_R_WSASTARTUP), "WSAStartup"},
{0, NULL}
};
这两个表通过ERR_load_BIO_strings函数来添加到错误信息哈希表中去。为了便于查找,所有模块的错误信息存放在一个全局哈希表中,在crypto/err/err.c实现。
2.2.2 ERR_STATE
typedef struct err_state_st
{
int err_flags[ERR_NUM_ERRORS];
unsigned long err_buffer[ERR_NUM_ERRORS]; //第i层错误码,包含库、函数以及错误原因信息。
char *err_data[ERR_NUM_ERRORS]; //存放第i层操作信息。
int err_data_flags[ERR_NUM_ERRORS]; /*存放err_data[i]相关的标记;比如:
为ERR_TXT_MALLOCED时,表err_data[i]动态分配内存的,需要释放;
为ERR_TXT_STRING表名err_data[i]中的数据是一个字符串,可以用来打印。*/
const char *err_file[ERR_NUM_ERRORS]; //第i层错误的文件名。
int err_line[ERR_NUM_ERRORS]; //第i层错误的行号。
int top, bottom; //用于指明ERR_STATE的使用状态。
//top对应与最后一个错误(错误堆栈的最上层)
//bottom对应第一个错误(错误堆栈的最底层)。
} ERR_STATE;
该结构用于存放和获取错误信息。由于可能会有多层函数调用(错误堆栈),这些信息都是一个数组。每个数组代表了一层函数的错误信息。用户需要扩展openssl的模块时,可以仿照其他已有模块来实现自己的错误处理。
3 相关函数
3.1 获取错误代码
每当有ERROR产生,一些重要的信息会被记录下来。一些信息可用于尝试自动恢复错误,但是其中的大多数都是用于调试和向用户报告错误。有6个API用于从Error队列中获取信息。ERROR是依产生的顺序记录在队列中的,这些函数都能获取到当前队列中最早的信息。
最基本的消息是一个32-bit integer型的Error code。如果Error队列中无任何消息,error处理函数将返回0,0不是一个有效的错误号。
9个获取error信息的API,实质上都是对get_error_values()的不同参数调用。
//只获取错误代码
unsigned long ERR_get_error(void); //获取第一个,并将其移除队列
unsigned long ERR_peek_error(void); //获取第一个,不移除队列
unsigned long ERR_peek_last_error(void); //获取最后一个,不移除队列
//获取Error code、错误产生的源文件(file)、行号(line)
unsigned long ERR_get_error_line(const char **file, int *line);
unsigned long ERR_peek_error_line(const char **file, int *line);
unsigned long ERR_peek_last_error_line(const char **file, int *line);
//获取Error code,错误产生的源文件(file)、行号(line),另提供额外的数据及标识如何处理这些数据的flag
unsigned long ERR_get_error_line_data(const char **file, int *line,
const char **data, int *flags);
unsigned long ERR_peek_error_line_data(const char **file, int *line,
const char **data, int *flags);
unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
const char **data, int *flags);
//所获得的数据可能是任意的,但大多数情况下会是一个字符串。
//如flag的ERR_TXT_MALLOCED被置1,则data所使用的内存可以使用OPENSSL_free函数释放。
//如flag的ERR_TXT_STRING被置1,则相应的data可以按C-style字串使用。
例:打印error队列
void print_errors(void)
{
int flags, line;
char *data, *file;
unsigned long code;
code = ERR_get_error_line_data(&file, &line, &data, &flags);
while(code)
{
printf("error code: %lu in %s line %d.\n", code, file, line);
if(data && (flags & ERR_TXT_STRING))
printf("error data: %s\n", data);
code = ERR_get_error_line_data(&file, &line, &data, &flags);
}
}
3.2 获取错误码对应的错误消息
error handling package为其定义的error code提供标准的错误消息,但是在使用前需被载入。
// libcrypto和libssl的错误消息全部载入
void SSL_load_error_strings(void)
{
#ifndef OPENSSL_NO_ERR
ERR_load_crypto_strings();
ERR_load_SSL_strings();
#endif:
}
//libcrypto的错误消息的载入
void ERR_load_crypto_strings(void)
{
#ifndef OPENSSL_NO_ERR
ERR_load_ERR_strings(); /* include error strings for SYSerr */
ERR_load_BN_strings();
#ifndef OPENSSL_NO_RSA
ERR_load_RSA_strings();
#endif
#ifndef OPENSSL_NO_DH
ERR_load_DH_strings();
#endif
ERR_load_EVP_strings();
ERR_load_BUF_strings();
ERR_load_OBJ_strings();
ERR_load_PEM_strings();
#ifndef OPENSSL_NO_DSA
ERR_load_DSA_strings();
#endif
ERR_load_X509_strings();
ERR_load_ASN1_strings();
ERR_load_CONF_strings();
ERR_load_CRYPTO_strings();
ERR_load_COMP_strings();
#ifndef OPENSSL_NO_EC
ERR_load_EC_strings();
#endif
#ifndef OPENSSL_NO_ECDSA
ERR_load_ECDSA_strings();
#endif
#ifndef OPENSSL_NO_ECDH
ERR_load_ECDH_strings();
#endif
/* skip ERR_load_SSL_strings() because it is not in this library */
ERR_load_BIO_strings();
ERR_load_PKCS7_strings();
ERR_load_X509V3_strings();
ERR_load_PKCS12_strings();
ERR_load_RAND_strings();
ERR_load_DSO_strings();
ERR_load_TS_strings();
#ifndef OPENSSL_NO_ENGINE
ERR_load_ENGINE_strings();
#endif
ERR_load_OCSP_strings();
ERR_load_UI_strings();
#ifndef OPENSSL_NO_CMS
ERR_load_CMS_strings();
#endif
#ifndef OPENSSL_NO_JPAKE
ERR_load_JPAKE_strings();
#endif
ERR_load_COMP_strings();
#endif
#ifdef OPENSSL_FIPS
ERR_load_FIPS_strings();
#endif
}
// libssl的错误消息的载入
void ERR_load_SSL_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(SSL_str_functs[0].error) == NULL)
{
ERR_load_strings(0,SSL_str_functs);
ERR_load_strings(0,SSL_str_reasons);
}
#endif
}
获取错误消息:
//获取全部错误消息
char* ERR_error_string(unsigned long e, char *buf)
void ERR_error_string_n(unsigned long e, char *buf, size_t len)
//获取错误发生的 库,函数,原因
const char *ERR_lib_error_string(unsigned long e);
const char *ERR_func_error_string(unsigned long e);
const char *ERR_reason_error_string(unsigned long e);
参数e : error code
参数buf:error message(最少256Byte)
参数len: 写入的消息的最大长度
error message的格式:
error:error code(hex):error name:产生error的函数名:产生error的原因
为了获取error信息,必需先获取错误代码ERR_get_error,然后转为错误消息ERR_error_string,OpenSSL提供了下列API来简化这个过程:
//生成一个error list并将其写入BIO
void ERR_print_errors(BIO *bp)
{
ERR_print_errors_cb(print_bio, bp);
}
//生成一个error list并将其写入一个标准的C FILE对象
void ERR_print_errors_fp(FILE *fp)
{
ERR_print_errors_cb(print_fp, fp);
}
3.3 其它函数
- ERR_add_error_data
在本层错误的err_data元素中添加说明信息。该函数一般由各个模块调用,比如可以用它说明什么操作导致了错误。
- ERR_clear_error
清除所有的错误信息。如果不清楚所有错误信息,可能会有其他无关错误遗留在ERR_STATE表中。
- ERR_free_strings
释放错误信息哈希表;通常在最后调用。
- ERR_get_err_state_table
获取存放错误的哈希表。
- ERR_get_implementation
获取错误处理函数,与哈希表操作相关。
- ERR_get_state
获取ERR_STATE表。
- ERR_load_strings
加载错误信息,由各个模块调用。
各个模块实现的,加载各自错误信息。
ERR_load_ASN1_strings
ERR_load_BIO_strings
ERR_load_BN_strings
ERR_load_BUF_strings
ERR_load_COMP_strings
ERR_load_CONF_strings
ERR_load_CRYPTO_strings
ERR_load_crypto_strings
ERR_load_DH_strings
ERR_load_DSA_strings
ERR_load_DSO_strings
ERR_load_EC_strings
ERR_load_ENGINE_strings
ERR_load_ERR_strings
ERR_load_EVP_strings
ERR_load_OBJ_strings
ERR_load_OCSP_strings
ERR_load_PEM_strings
ERR_load_PKCS12_strings
ERR_load_PKCS7_strings
ERR_load_RAND_strings
ERR_load_RSA_strings
ERR_load_UI_strings
ERR_load_X509_strings
ERR_load_X509V3_stringsERR_print_errors
将错误信息输出到bio中。
- ERR_print_errors_cb
根据用户设置的回调函数来打印错误信息。
- ERR_print_errors_fp
将错误打印到FILE中。
- ERR_put_error
将错误信息存放到ERR_STATE 表中top指定的错误堆栈(最后的错误)。
- ERR_remove_state
删除线程相关的错误信息。
- ERR_set_error_data
将错误信息存放到ERR_STATE 表中top指定的错误堆栈(最后的错误)。
- ERR_unload_strings
从错误哈希表中删除相关信息。
版权声明:本文根据DragonKing牛,E-Mail:wzhah@263.NET发布在https://openssl.126.com的系列文章整理修改而成(这个网站已经不能访问了),我自己所做的工作主要是针对新的1.0.2版本进行验证,修改错别字,和错误,重新排版,以及整理分类,配图。 未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处,这是对原创者的起码的尊重!!!
本文详细介绍了OpenSSL中ERR库的功能,包括错误代码的结构、数据结构ERR_STRING_DATA和ERR_STATE,以及如何获取和处理错误信息。内容涵盖错误代码的计算、错误堆栈、错误信息的加载和清除,强调了错误处理在程序设计中的重要性。
1669

被折叠的 条评论
为什么被折叠?



