Memory management C++;CLI自动删除非托管对象

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;

我有一个简单的本机类,它每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;

    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);
}