У меня есть следующий код:Ошибки при удалении зОго :: вектора в DLL с помощью Pimpl идиомы
В Dll1:
в файле .h:
class MyClass
{
public:
MyClass();
private:
std::string m_name;
};
class __declspec(dllexport) Foo
{
private:
struct Impl;
Impl *pimpl;
public:
Foo();
virtual ~Foo();
};
struct Foo::Impl
{
std::vector<MyClass> m_vec;
std::vector<MyClass> &GetVector() { return m_vec; };
};
в .cpp файл:
Foo::Foo() : pimpl (new Impl)
{
}
Foo::~Foo()
{
delete pimpl;
pimpl = NULL;
}
[EDIT]
В DLL2
в .h
class Bar : public Foo
{
public:
Bar();
virtual ~Bar();
};
в .cpp:
Bar::Bar()
{
}
Bar::~Bar()
{
}
В DLL3:
extern "C" __declspec(dllexport) Foo *MyFunc(Foo *param)
{
if(!param)
param = new Bar();
return param;
}
В основном приложении:
void Abc::my_func()
{
Foo *var = NULL;
// loading the DLL3 and getting the address of the function MyFunc
var = func(var);
delete var;
}
Теперь я предполагаю, что конструктор копирования должен быть закрытым, так как нет смысла копировать объекты Foo и Bar.
Теперь у меня есть вопрос: должен ли Bar также иметь экземпляр-конструктор и оператор присваивания? [/ EDIT]
Обратите внимание, что MyClass не экспортируется и не имеет деструктора.
Как правило, вы пишете код?
Проблема в том, что я столкнулся с Windows (8.1 + MSVC 2010, если это имеет значение). Я могу отправить больше кода, если это необходимо, но на данный момент просто хочу убедиться, что я не делаю что-то явно неправильно.
Катастрофа происходит после того, как я выхожу из базы деструктора и трассировки стека говорит:
ntdll.dll 770873a6() [Фреймы ниже могут быть неправильными и/или отсутствует, никакие символы не загружены для ntdll.dll] ntdll.dll! 7704164f()
ntdll.dll! 77010f01() KernelBase.dll! 754a2844()
dll1.dll! _CrtIsValidHeapPointer (сопзЬ пустота * pUserData) линия 2036 C++ dll1.dll! _free_dbg_nolock (void * pUserData, int nBlockUse) Строка 1322 + 0x9 байт C++ dll1.dll! _free_dbg (void * pUserData, int nBlockUse) Линия 1265 + 0xD байт C++ dll1.dll! Оператор удаления (аннулируются * pUserData) Строка 54 + 0x10 байт C++ dll1.dll! Foo :: `вектор удаления деструктор '() + 0x65 байт C++
Спасибо.
UPDATE:
Даже если я ставлю следующий код в
extern "C" __declspec(dllexport) Foo *MyFunc(Foo *param)
{
param = new Bar();
delete param;
return param;
}
Программа по-прежнему сбой в операции удаления паров в том же месте.
Похоже, деструктор std :: vector вызывается позже, после вызова деструктора Foo. Так оно и должно быть?
UPDATE2:
После тщательного запуска этого под отладчиком, я вижу, что авария происходит внутри «аннулируется оператор удаления (пустота * pUserData);». Указатель pUserData имеет адрес «param».
Dll1 построен с этим:
C++
/ZI/NOLOGO/W4/WX-/Od/Oy-/D "WIN32"/D "_DEBUG"/D «_LIB "/ D " _UNICODE "/ D" UNICODE "/ Gm/EHsc/RTC1/MTd/GS/fp: точный /Zc: wchar_t/Zc: forScope /Fp"Debug\dll1.pch"/Fa "Debug \"/Fo "Debug \" /Fd"Debug\vc100.pdb "/ Б/analyze-/errorReport: очереди
Библиотекарь /OUT:" C: \ Users \ Игорь \ OneDrive \ Docu Ментов \ dbhandler1 \ docview \ Debug \ dll1.lib» /NOLOGO
DLL2 был построен с:
C++
/I"..\dll1\" /Zi /nologo /W4 /WX- /Od /Oy- /D "WIN32" /D "_USRDLL" /D "DLL_EXPORTS" /D "_DEBUG" /D "_CRT_SECURE_NO_DEPRECATE=1" /D "_CRT_NON_CONFORMING_SWPRINTFS=1" /D "_SCL_SECURE_NO_WARNINGS=1" /D "_UNICODE" /D "MY_DLL_BUILDING" /D "_WINDLL" /D "UNICODE" /Gm- /EHsc /RTC1 /MTd /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fp"vc_mswud\dll2\dll2.pch" /Fa"vc_mswud\dll2\" /Fo"vc_mswud\dll2\" /Fd"vc_mswud\dll2.pdb" /Gd /analyze- /errorReport:queue
Linker
/OUT:"..\myapp\vc_mswud\dll2.dll" /INCREMENTAL /NOLOGO /LIBPATH:"..\docview\Debug\" /DLL "dll1.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "comdlg32.lib" "winspool.lib" "winmm.lib" "shell32.lib" "shlwapi.lib" "comctl32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "rpcrt4.lib" "advapi32.lib" "version.lib" "wsock32.lib" "wininet.lib" /MANIFEST /ManifestFile:"vc_mswud\dll2\dll2.dll.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"vc_mswud\dll2.pdb" /PGD:"C:\Users\Igor\OneDrive\Documents\myapp\dll2\vc_mswud\dll2.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"vc_mswud\dll2.lib" /MACHINE:X86 /ERRORREPORT:QUEUE
Видит ли кто-либо проблем с тем, как мои библиотеки построены?
Надеюсь, вы никогда не сделаете копию 'Foo', потому что созданный компилятором экземпляр будет выполнять мелкую копию' pimpl', что приведет к двойному удалению. – AndyG
Вы не следуете правилам Трех. Теперь, с учетом этого, я думаю, вы должны показать, как вы используете 'Foo'. Неясно, следуете ли вы указаниям по распределению памяти и освобождению библиотек DLL. В частности, тот, кто выделил 'Foo', должен освободить' Foo'. Это так? – paddy
Это не проблема, но нет смысла устанавливать 'pimpl' в' NULL' в деструкторе 'Foo'. Объект уходит, поэтому 'pimpl' тоже уходит. –