Memory management C++;CLI自动删除非托管对象
我有一个简单的本机类,它每9秒在一个目录中创建一个小文件Memory management C++;CLI自动删除非托管对象,memory-management,c++-cli,marshalling,Memory Management,C++ Cli,Marshalling,我有一个简单的本机类,它每9秒在一个目录中创建一个小文件 void SampleClass::DoWork(char *directoryPath, SegmentCreatedDelegate callback, bool *cancel) { if(*cancel) return; char* segmentFileName = "test%d.ts"; // open the file to write FILE *pFilempegTs = NULL;
void SampleClass::DoWork(char *directoryPath, SegmentCreatedDelegate callback, bool *cancel)
{
if(*cancel) return;
char* segmentFileName = "test%d.ts";
// open the file to write
FILE *pFilempegTs = NULL;
int segmentIndex = 0;
clock_t beginingTime = clock();
char currentSegmentPath[256];
while(!*cancel)
{
// create the segment file to write if we haven't already.
if(pFilempegTs == NULL)
{
segmentIndex++;
strncpy(currentSegmentPath, directoryPath, sizeof(currentSegmentPath));
strncat(currentSegmentPath, segmentFileName, sizeof(currentSegmentPath));
sprintf(currentSegmentPath, currentSegmentPath, segmentIndex);
if( (pFilempegTs = fopen(currentSegmentPath, "wb" )) == NULL )
{
std::cout << "The file can not be opened for writing\n";
return;
}
}
if((double(clock() - beginingTime) / CLOCKS_PER_SEC) >= 9)
{
fclose(pFilempegTs);
pFilempegTs = NULL;
callback(currentSegmentPath); // the moment I invoke the delegate, the currentSegmentPath gets deleted.
beginingTime = clock();
}
}
if(pFilempegTs != NULL)
{
fclose(pFilempegTs);
callback(currentSegmentPath); // the moment I invoke the delegate, the currentSegmentPath gets deleted.
}
return;
}
为什么仅当本机方法在c++/cli项目之外编译时,才调用分段CreatedElegate
删除currentSegmentPath
这正是我收到的错误信息
试图读取或写入受保护的内存。这通常是一个问题
表示其他内存已损坏
更新
我创建了一个示例项目来重现这个问题
更新2
我为我的托管委托添加了一个
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
属性,我的问题似乎得到了解决。这两个项目都使用cdecl调用约定,所以我不知道为什么需要这样做。这可能与调用约定冲突。如上所述,非托管程序集和混合程序集使用调用转换,但对于纯托管程序集,生成器默认使用
尝试使用相同的调用约定编译两个DLL。对于VS 2010,这可以在项目属性->C/C++->高级->调用约定中完成。不要在
IntPtr
上执行(SegmentCreatedElegate)(void*)回调指针。相反,(SegmentCreatedElegate)callbackPointer.ToPointer()
请同时显示SegmentCreatedElegate
的typedef您的代理声明错误,听起来您没有进步。你以前的代码没有崩溃是一个不幸的事故。“currentSegmentPath”变量不能被“删除”,它是一个局部变量。你已经被困在这个问题上够久了,为了得到你需要的帮助,你必须向文件共享服务发布一个小的复制解决方案来演示这个问题,这样我们才能真正地复制这个问题。我创建了一个示例项目,你可以用它来复制这个问题。在释放模式下运行程序。
void SampleClassNet::DoWork(System::String^ directoryPath, SegmentCreatedDelegateNet^ segmentCreatedCallback, bool% cancel)
{
SampleClass* nativeClass = new SampleClass();
System::IntPtr directoryPathPointer = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(directoryPath);
char *directoryPathNative = static_cast<char*>(directoryPathPointer.ToPointer());
System::IntPtr callbackPointer = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(segmentCreatedCallback);
pin_ptr<bool> pinnedCancel = &cancel;
bool* pinnedCancelRef = pinnedCancel;
nativeClass->DoWork(directoryPathNative, (SegmentCreatedDelegate)(void*)callbackPointer, pinnedCancelRef);
System::GC::KeepAlive(segmentCreatedCallback);
System::Runtime::InteropServices::Marshal::FreeHGlobal(directoryPathPointer);
}