c ++ openssl 1.1.1, выполняющий алгоритм RSA в потоке, вызывающий утечки памяти - PullRequest
0 голосов
/ 06 февраля 2020

Это очень странно! Я смотрю вокруг и ничего не нахожу. Мой тестовый код ниже:

#include "pch.h"
#include "Windows.h"
#include "openssl/ssl.h"

#pragma comment(lib,"../Include/lib/libssl.lib")
#pragma comment(lib,"../Include/lib/libcrypto.lib")
#pragma comment(lib,"Crypt32.lib")
#pragma comment(lib,"ws2_32.lib")

#include <stdlib.h>
#include <crtdbg.h>

#define _CRTDBG_MAP_ALLOC

const char* priKey = "607BC8BA457EC0A1B5ABAD88061502BEA5844E17C7DD247345CD57E501B3300B4B8889D3DFCF5017847606508DF8B283C701F35007D5F4DBA96023DD3B0CCE062D8F63BCC16021B944A1E88861B70D456BAA1E0E69C90DFCA13B4D4EA5403DA25FEBF94B0515644A7D2DF88299189688DA5D8951512ADC3B1A35BAEEC147F69AB101048B9029E65A77A438A05AE30337E82B0571B80A955C72EA0DB3B457ECC8B81F346624E3D22755FEB3D84F810431974803E13E26BF95AF7AB590E17C0113BFE9B36BE12BE16D89273348E0CC094526CAF54ABF8044565EC9500EBF657265474BC362EBDFD78F513282AAF0EEF9BA0BB00F7FF9C7E61F00465BBD379D6201";
const char* pubKey = "AE7DF3EB95DF1F864F86DA9952BB44E760152986731253C96C135E5391AEFF68F5C1640552F1CCC2BA2C12C0C68C051E343B786F13215CEFC8221D9FA97D50E895EAF50D1AF32DC5EB40C9F1F8CA5145B43CEF83F2A89C9661AFA73A70D32951271C6BEFE1B5F24B512520DA7FD4EEC982F2D8057FE1938FA2FB54D8D282A25D8397298B75E154739EF16B8E2F18368F5BEEAD3D18528B9B1A63C731A71735CDB6102E187EF3377B72B58A124FA280891A79A2BD789D5DBA3618BBD74367F5C50A220204D90A59828C3C81FDBD9D2A91CBF6C8563C6FE987BE21B19BBC340DE4D42290D63909AD5D856D13B8CDC91D5701570045CE3609D4F8884F69120AD9A3";

void rsa_test(const char* n,const char* d)
{
    RSA* rsa = RSA_new();

    BIGNUM* bn = BN_new();
    BIGNUM* bd = BN_new();
    BIGNUM* be = BN_new();
    BN_set_word(be, 0x10001);
    if (n) BN_hex2bn(&bn, n);

    if (d) BN_hex2bn(&bd, d);
    RSA_set0_key(rsa, bn, be, bd);

    //calc hash
    const char* msg = "hello,rsa!!";
    BYTE shaResult[SHA256_DIGEST_LENGTH] = { 0 };
    SHA256((unsigned char*)msg, strlen(msg), shaResult);

    //sign
    unsigned int olen;
    unsigned char sign[256] = { 0 };
    RSA_sign(NID_sha256, shaResult, SHA256_DIGEST_LENGTH, sign, &olen,rsa);

    RSA_free(rsa);
}

DWORD thread_test(LPVOID lpParam)
{
    rsa_test(pubKey, priKey);
    return 0;
}

int main()
{
    //_CrtSetBreakAlloc(159);

    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    //CreateThread(nullptr, 0, thread_test, nullptr, 0, nullptr);
    //rsa_test(pubKey,priKey);

    system("pause");
}

Вызов rsa_test (pubKey, priKey) непосредственно в главном потоке НЕ вызывает утечек памяти!

Вызов CreateThread (nullptr, 0, thread_test, nullptr, 0, nullptr) выходит утечка памяти !!!

Вывод на консоль следующим образом:

Detected memory leaks!
Dumping objects ->
{173} normal block at 0x000002BDE6D44000, 264 bytes long.
 Data: <   _W- :_ s  ! 6> D8 89 FD 5F 57 2D C5 3A 5F 82 73 F1 00 21 FA 36 
{162} normal block at 0x000002BDE6D43AC0, 264 bytes long.
 Data: <                > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
{161} normal block at 0x000002BDE6D2E2A0, 160 bytes long.
 Data: <`               > 60 F1 0F 91 F6 7F 00 00 00 00 00 00 00 00 00 00 
{160} normal block at 0x000002BDE6D2DBA0, 160 bytes long.
 Data: <`               > 60 F1 0F 91 F6 7F 00 00 00 00 00 00 00 00 00 00 
{159} normal block at 0x000002BDE6D48230, 352 bytes long.
 Data: <        P       > 00 00 00 00 00 00 00 00 50 AB D3 E6 BD 02 00 00 
{158} normal block at 0x000002BDE6D286B0, 12 bytes long.
 Data: <            > 00 00 00 00 00 00 00 00 01 00 00 00 
Object dump complete.

Тогда Я использую _CrtSetBreakAllo c (159) (или другой идентификатор памяти) для определения местоположения, и вот мой скриншот стека вызовов: call stack

мой показ vs2017 точка останова на CRYPTO_zallo c (crypto / mem. c)

Так что мой вопрос, как освободить эти утечки памяти в потоке!

Спасибо лот !!

Загрузить мой тестовый код (сборка с Visual Studio 2017 x64)

1 Ответ

2 голосов
/ 06 февраля 2020

https://www.openssl.org/docs/man1.1.0/man3/OPENSSL_thread_stop.html

    OPENSSL_thread_stop();

сделает это за вас. Вы можете назвать это как ниже

DWORD thread_test(LPVOID lpParam)
{
    rsa_test(pubKey, priKey);
    OPENSSL_thread_stop();
    return 0;
}
...