在OpenSSL中,错误堆栈和错误队列是否相同?

在OpenSSL中,错误堆栈和错误队列是否相同?,openssl,Openssl,在openSSL文档中,我一直在阅读错误队列和错误堆栈。 这两种描述是否都指向相同的机制?或者它们是不同的机制 我一直在读取错误队列和错误堆栈。这两种描述是否都指向相同的机制?或者它们是不同的机制 据我所知,他们都是一样的,是付出还是索取。它们大多可以互换使用 错误队列是逻辑性的,它通常被抽象地讨论。库至少有两个不同的错误队列。第一个是来自libcrypto的,您可以使用ERR\u get\u error获取其错误。第二个是来自libssl,您可以使用SSL\u get\u error获取错误

在openSSL文档中,我一直在阅读错误队列和错误堆栈。 这两种描述是否都指向相同的机制?或者它们是不同的机制

我一直在读取错误队列和错误堆栈。这两种描述是否都指向相同的机制?或者它们是不同的机制

据我所知,他们都是一样的,是付出还是索取。它们大多可以互换使用

错误队列是逻辑性的,它通常被抽象地讨论。库至少有两个不同的错误队列。第一个是来自
libcrypto
的,您可以使用
ERR\u get\u error
获取其错误。第二个是来自
libssl
,您可以使用
SSL\u get\u error
获取错误

错误堆栈实际上是错误队列的一个实现。下面是libcrypto在代码中的样子。它在
crypto/err/err.h
中声明,并在
crypto/err/err.c
中实现:

unsigned long ERR_get_error(void)
{
    return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
}
以及:

以及:


ERR.*
是一个队列,主要用于实际错误
SSL\u get\u error()
是独立的,但不是队列;它是单个小整数值,用于真实错误和有效但需要区分的情况;一个更准确但不太方便的名称是
SSL\u获取\u任何\u状态\u除了\u完全\u正常\u完成\u操作()
。请检查我的理解。如果以SSL_read()为例:在调用SSL_read()之前,我调用ERR_clear_error(),然后调用SSL_read(),如果从SSL_read()返回
static unsigned long get_error_values(int inc, int top, const char **file,
                                      int *line, const char **data,
                                      int *flags)
{
    int i = 0;
    ERR_STATE *es;
    unsigned long ret;

    es = ERR_get_state();

    if (inc && top) {
        if (file)
            *file = "";
        if (line)
            *line = 0;
        if (data)
            *data = "";
        if (flags)
            *flags = 0;

        return ERR_R_INTERNAL_ERROR;
    }

    if (es->bottom == es->top)
        return 0;
    if (top)
        i = es->top;            /* last error */
    else
        i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */

    ret = es->err_buffer[i];
    if (inc) {
        es->bottom = i;
        es->err_buffer[i] = 0;
    }

    if ((file != NULL) && (line != NULL)) {
        if (es->err_file[i] == NULL) {
            *file = "NA";
            if (line != NULL)
                *line = 0;
        } else {
            *file = es->err_file[i];
            if (line != NULL)
                *line = es->err_line[i];
        }
    }

    if (data == NULL) {
        if (inc) {
            err_clear_data(es, i);
        }
    } else {
        if (es->err_data[i] == NULL) {
            *data = "";
            if (flags != NULL)
                *flags = 0;
        } else {
            *data = es->err_data[i];
            if (flags != NULL)
                *flags = es->err_data_flags[i];
        }
    }
    return ret;
}
ERR_STATE *ERR_get_state(void)
{
    static ERR_STATE fallback;
    ERR_STATE *ret, tmp, *tmpp = NULL;
    int i;
    CRYPTO_THREADID tid;

    err_fns_check();
    CRYPTO_THREADID_current(&tid);
    CRYPTO_THREADID_cpy(&tmp.tid, &tid);
    ret = ERRFN(thread_get_item) (&tmp);

    /* ret == the error state, if NULL, make a new one */
    if (ret == NULL) {
        ret = (ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
        if (ret == NULL)
            return (&fallback);
        CRYPTO_THREADID_cpy(&ret->tid, &tid);
        ret->top = 0;
        ret->bottom = 0;
        for (i = 0; i < ERR_NUM_ERRORS; i++) {
            ret->err_data[i] = NULL;
            ret->err_data_flags[i] = 0;
        }
        tmpp = ERRFN(thread_set_item) (ret);
        /* To check if insertion failed, do a get. */
        if (ERRFN(thread_get_item) (ret) != ret) {
            ERR_STATE_free(ret); /* could not insert it */
            return (&fallback);
        }
        /*
         * If a race occured in this function and we came second, tmpp is the
         * first one that we just replaced.
         */
        if (tmpp)
            ERR_STATE_free(tmpp);
    }
    return ret;
}
$ grep -IR ERR_STATE * | grep DECLARE
crypto/err/err.c:DECLARE_LHASH_OF(ERR_STATE);