2017-03-08 1 views
4

Ich habe eine Funktion implementiert, wo die Identität mir und außerhalb meiner Kontrolle gegeben wird. Es gibt std::shared_ptr<const void> zurück. In der Funktion gebe ich eine willkürliche Menge an Speicher zu und gebe den Zugriff darauf durch den shared_ptr zurück.Richtiger Weg, Speicher std :: shared_ptr zuzuweisen

Meine Speicherzuweisung erfolgt mit new unsigned char[123]. Das Problem besteht darin, dass Valgrind eine Abweichung zwischen der Verwendung von neuen und Löschvarianten erkennt. Während ich new[](unsigned) verwenden, um Speicher zuzuordnen, verwendet der shared_ptr-Destruktor delete(void*), um es aufzuheben, und Valgrind warnt, wann immer Sie die "inkorrekte" Freigabe für eine Zuordnung verwenden.

In praktischer Hinsicht, ich schrieb diesen Testfall um zu zeigen, was ich meine:

TEST(Example, Test1) 
{ 
    unsigned char* mem = new unsigned char[123]; 
    std::shared_ptr<const void> ptr(mem); 
} 

Der valgrind Bericht sagt

==45794== Mismatched free()/delete/delete [] 
==45794== at 0x4C2A64B: operator delete(void*) (vg_replace_malloc.c:576) 
==45794== by 0x40B7B5: _M_release (shared_ptr_base.h:150) 
==45794== by 0x40B7B5: ~__shared_count (shared_ptr_base.h:659) 
==45794== by 0x40B7B5: ~__shared_ptr (shared_ptr_base.h:925) 
==45794== by 0x40B7B5: ~shared_ptr (shared_ptr.h:93) 
==45794== by 0x40B7B5: Example_Test1_Test::TestBody() (test.cc:108) 
==45794== Address 0x5cb6290 is 0 bytes inside a block of size 123 alloc'd 
==45794== at 0x4C29CAF: operator new[](unsigned long) (vg_replace_malloc.c:423) 
==45794== by 0x40B72E: Example_Test1_Test::TestBody() (test.cc:107) 

Ich möchte valgrind Filter, wenn möglich zu vermeiden.

Was ist die richtige Weise, eine beliebige Menge von Daten zuzuordnen und als std::shared_ptr<const void> zurückzukehren?

+0

Wie sieht es mit der Zuweisung mit malloc aus? – Yury

+0

Wenn Sie stattdessen 'malloc' verwenden, erhalten Sie eine ähnliche Warnung, weil Sie nicht mit' free' übereinstimmen. – Martin

Antwort

13

Wenn Sie shared_ptr<T> einen T Zeiger angeben, wird davon ausgegangen, dass Sie ein einzelnes Objekt erstellt haben und den Löschvorgang delete p; impliziert. Wenn Ihre Zuweisung tatsächlich mit Array-Neu durchgeführt wurde, müssen Sie einen entsprechenden Deleter übergeben, der delete[] p; ausführt. Sie können std::default_delete wiederverwenden, wenn Sie möchten: (. Sie brauchen nicht einmal die äußere Guss, da die Umwandlung impliziert)

return static_pointer_cast<const void>(
    std::shared_ptr<unsigned char>(
     new unsigned char[N], 
     std::default_delete<unsigned char[]>())); 

In C++ 17, shared_ptr Arrays unterstützt, so können Sie sagen

shared_ptr<unsigned char[]>(new unsigned char[N]) 

dort und bekommt die richtigen deleter (und dann konvertieren ungültig zu erklären).

+0

[Demo] (http://melpon.org/wandbox/permlink/24Or4rgU851gtSYx), [modifizierte Demo] (http://melpon.org/wandbox/permlink/tzFXH0NyKUPTht5E). –

+0

Danke, funktioniert wie ein Zauber – Martin

Verwandte Themen