2016-12-16 7 views
0

В принципе, это то, что у меня есть:shared_ptr <EVP_PKEY> с EVP_PKEY_free как пользовательские Deleter вызывает повреждение кучи

{ 
    shared_ptr<EVP_PKEY> evpKeyPtr{EVP_PKEY_new(), EVP_PKEY_free}; 
    //get key from file 
} 

Это вызывает повреждение кучи. Так же, как это:

shared_ptr<EVP_PKEY> evpKeyPtr{EVP_PKEY_new(), EVP_PKEY_free}; 
//same code as above to get key from file 
EVP_PKEY_free(evpKeyPtr.get()); 
//evpKeyPtr does not go out of scope before the corruption occurs 

Но это не делает:

EVP_PKEY* evpKey = EVP_PKEY_new(); 
//same code as above to get key from file 
EVP_PKEY_free(evpKey); 

Я в недоумении, почему это может происходить. Я знаю, что второй код не рекомендуется, но я сделал это, чтобы проверить, что произойдет.

+0

Вам необходимо опубликовать полный, компилируемый, исполняемый тестовый пример, который воспроизводит проблему. – xaxxon

+0

Может быть, 'std :: shared_ptr evpKeyPtr (EVP_PKEY_new(), [] (EVP_PKEY * p) {EVP_PKEY_free (p);});'? –

+0

Возможно, вы захотите попробовать C++ 11 и 'unique_ptr'. Я использую его часто, и я знаю, что он работает. Я никогда не пробовал шаблон C++ 03 и 'shared_ptr'. Для этого я считаю, что вам нужно вызвать 'release' (а не' get'): 'EVP_PKEY_free (evpKeyPtr.release())'. Когда вы вызываете 'release', вы больше не можете использовать' evpKeyPtr'. – jww

ответ

1

вы просто получаете указатель, но shared_ptr остается его владельцем. он будет удален дважды в конце области действия.

Если вы хотите, чтобы получить право собственности, используйте unique_ptr (у него есть метод release()).

+0

Общий_разряд в среднем коде не то, о чем мой вопрос. Однако shared_ptr не выходил за пределы области действия до того, как произошло повреждение кучи (т. Е. Shared_ptr все еще принадлежал указателю и вызывал EVP_PKEY_free на get(), вызвало повреждение кучи). –

+0

shared_ptr всегда выводит управляемый ресурс в свой деструктор, если указатель на него! = Nullptr. но вы пытаетесь удалить его вручную в объеме без получения прав собственности. –

+0

не просто пытается, вы удаляете его с помощью 'EVP_PKEY_free (evpKeyPtr.get())' ;. –

0

Я только что понял, что я делаю неправильно, и он имеет (почти) ничего общего с std::shared_ptr. Я пытался использовать временный указатель на указатель std::shared_ptr неправильным образом.