代码中出现std::bad_alloc的原因是什么?



最近我写了这段代码,我注意到这里的某个地方导致

terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc

下面是我的代码:
namespace logger {
set<string> pendingLogs;
bool isDebugEnabled = false;
mutex logMutex;
inline void add_log_to_pending(const string &text) {
lock_guard<mutex> guard(logMutex);
cout << "[Logger] Adding: " << text << endl;
pendingLogs.insert(text);
}
inline string grab_logs() {
string collector;
lock_guard<mutex> guard(logMutex);
if (pendingLogs.empty()) return collector;
for (const auto& item: pendingLogs) {
collector += item + "n";
}
pendingLogs.clear();
return collector;
}
}

启动线程代码:

std::thread log_composer_thread(&log_composer_callable);
log_composer_thread.detach();

函数线程代码:

[[noreturn]] void log_composer_callable() {
logger::log_debug("Log composer thread started..");
while (true) {
const string &logs = logger::grab_logs();
if (logs.empty()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
continue;
}
//send logic
}
}

是什么导致了这个错误?我认为它与curl库有关,但当I禁用时整个日志逻辑,所有错误都消失了所以这就是为什么我认为错误是在记录器代码的某个地方

编辑1:

inline std::vector<unsigned char>
rsa_encrypt_pubkey(EVP_PKEY *pubKey, unsigned char *toEncrypt, size_t toEncryptLength, bool eraseInputArray) {
size_t outlen;
if (toEncryptLength > 256) {
logger::add_log_to_pending("Error: rsa_encrypt_pubkey: toEncryptLength > 256");
return {};
}
//init the cipher context for encryption using the public key
EVP_PKEY_CTX *enc_ctx = EVP_PKEY_CTX_new(pubKey, nullptr);
EVP_PKEY_encrypt_init(enc_ctx);
EVP_PKEY_CTX_set_rsa_padding(enc_ctx, RSA_PKCS1_OAEP_PADDING);
EVP_PKEY_CTX_set_rsa_oaep_md(enc_ctx, EVP_sha256());
//determine output length
if (!EVP_PKEY_encrypt(enc_ctx, nullptr, &outlen, toEncrypt, toEncryptLength)) {
logger::add_log_to_pending("Error: EVP_PKEY_encrypt | " + string(ERR_error_string(ERR_get_error(), nullptr)));
return {};
}
std::vector<unsigned char> encrypted(outlen);
#if debug_mode_advanced == 1
cout << "Output length: " << outlen << " toEncryptLenght: " << toEncryptLength << endl;
cout << ERR_error_string(ERR_get_error(), nullptr) << endl;
#endif
//final encrypt call
if (!EVP_PKEY_encrypt(enc_ctx, &encrypted[0], &outlen, toEncrypt, toEncryptLength)) {
logger::add_log_to_pending("Error: EVP_PKEY_encrypt | " + string(ERR_error_string(ERR_get_error(), nullptr)));
return {};
}
//clean up
EVP_PKEY_CTX_free(enc_ctx);
if (eraseInputArray) free(toEncrypt);
return encrypted;
}

导致问题的代码,这里的问题是什么?

编辑2:

inline vector<unsigned char>
rsa_encrypt_rewrite(unsigned char *in, size_t inlen, EVP_PKEY *key, bool eraseInputArray) {
try {
EVP_PKEY_CTX *ctx;
ENGINE *eng;
unsigned char *out;
size_t outlen;
if (inlen > 256) {
logger::add_log_to_pending("Error: rsa_encrypt_pubkey: toEncryptLength > 256");
return {};
}
ctx = EVP_PKEY_CTX_new(key, eng);
if (!ctx) {
logger::add_log_to_pending(
"Error: EVP_PKEY_CTX_new | " + string(ERR_error_string(ERR_get_error(), nullptr)));
return {};
}
/* Error occurred */
if (EVP_PKEY_encrypt_init(ctx) <= 0) {
logger::add_log_to_pending(
"Error: EVP_PKEY_encrypt_init | " + string(ERR_error_string(ERR_get_error(), nullptr)));
return {};
}
/* Error */
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
logger::add_log_to_pending(
"Error: EVP_PKEY_CTX_set_rsa_padding | " + string(ERR_error_string(ERR_get_error(), nullptr)));
return {};
}
/* Error */
/* Determine buffer length */
if (EVP_PKEY_encrypt(ctx, nullptr, &outlen, in, inlen) <= 0) {
logger::add_log_to_pending(
"Error: EVP_PKEY_encrypt | " + string(ERR_error_string(ERR_get_error(), nullptr)));
return {};
}
/* Error */
out = (unsigned char *) OPENSSL_malloc(outlen);
if (!out) {
logger::add_log_to_pending("Error: OPENSSL_malloc");
return {};
}
/* malloc failure */
if (EVP_PKEY_encrypt(ctx, out, &outlen, in, inlen) <= 0) {
logger::add_log_to_pending(
"Error: EVP_PKEY_encrypt | " + string(ERR_error_string(ERR_get_error(), nullptr)));
return {};
}
EVP_PKEY_CTX_free(ctx);
if (eraseInputArray) free(in);
vector<unsigned char> encrypted(out, out + outlen);
OPENSSL_free(out);
return encrypted;
} catch (const std::exception &e) {
logger::add_log_to_pending("Error: rsa_encrypt_rewrite general exception: " + string(e.what()));
return {};
}
}

代码看起来没问题吗?而bad_alloc不应该出现?

看起来问题在这部分代码:

if (!EVP_PKEY_encrypt(enc_ctx, nullptr, &outlen, toEncrypt, toEncryptLength)) {
logger::add_log_to_pending("Error: EVP_PKEY_encrypt | " + string(ERR_error_string(ERR_get_error(), nullptr)));
return {};
}
std::vector<unsigned char> encrypted(outlen);

考虑EVP_PKEY_encrypt()对于错误也可能返回一个负的值。你把所有非零的东西都视为成功。但是,如果失败,outlen可能没有被正确初始化,在这种情况下,它可能会持有一个巨大的数字,导致encrypted的构造函数耗尽内存,抛出std::bad_alloc

最新更新