У меня есть следующий код:
В 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;
}
[РЕДАКТИРОВАТЬ]
В DLL2
in .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 также иметь конструктор копирования и оператор присваивания? [/РЕДАКТИРОВАТЬ]
Обратите внимание, что MyClass не экспортируется и не имеет деструктора.
Это вообще то, как вы пишете код?
Проблема в том, что у меня сбой на Windows (8.1 + MSVC 2010, если это имеет значение). Я могу опубликовать больше кода, если это необходимо, но сейчас просто хочу убедиться, что я не делаю что-то явно неправильное.
Сбой происходит после того, как я выхожу из деструктора Base, и трассировка стека говорит:
ntdll.dll!770873a6() [Кадры ниже могут быть неверными и/или отсутствовать, символы для ntdll.dll не загружены] ntdll.dll!7704164f()
ntdll.dll!77010f01() KernelBase.dll!754a2844()
dll1.dll!_CrtIsValidHeapPointer(const void * 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!operator delete(void * pUserData) Строка 54 + 0x10 байт C++ dll1.dll!Foo::`vector deleting destructor'() + 0x65 байт C++
Спасибо.
ОБНОВИТЬ:
Даже если я поставлю следующий код в
extern "C" __declspec(dllexport) Foo *MyFunc(Foo *param)
{
param = new Bar();
delete param;
return param;
}
Программа все еще падает в операции удаления параметра в том же месте.
Похоже, что деструктор std::vector вызывается позже, после вызова деструктора Foo. Это как должно быть?
ОБНОВЛЕНИЕ2:
После тщательного запуска этого под отладчиком я вижу, что сбой происходит внутри «void operator delete (void *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:precise /Zc:wchar_t /Zc:forScope /Fp"Debug\dll1.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue
Библиотекарь /OUT: "C:\Users\Igor\OneDrive\Documents\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
, что приведет к двойному удалению. - person AndyG   schedule 02.02.2016Foo
. Неясно, следуете ли вы рекомендациям по выделению и освобождению памяти с помощью библиотек DLL. В частности, тот, кто выделилFoo
, должен освободитьFoo
. Так ли это? - person paddy   schedule 02.02.2016pimpl
вNULL
в деструктореFoo
. Объект уходит, поэтомуpimpl
тоже уходит. - person Pete Becker   schedule 02.02.2016Base
, поэтому с ошибками, выходящими из его деструктора, очень трудно помочь. - person TBBle   schedule 02.02.2016NULL
на копию. Попробуйте отключить (=delete
) или реализовать конструктор копирования и посмотреть, что произойдет. - person AndyG   schedule 02.02.2016class Base
. - person TBBle   schedule 04.02.2016dll1.dll!Foo::`vector deleting destructor'
не является деструктором std::vector. Это «окончательный код очистки» Foo, поэтому код, который запускается сразу после завершения написанного кода~Foo
. Это внутренняя деталь объектной модели Visual C++. . - person TBBle   schedule 06.02.2016Impl* pImpl
простымbool
, произойдет то же самое. - person TBBle   schedule 06.02.2016