Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ P/Invoke:指针内存损坏_C++_Mono_Pinvoke - Fatal编程技术网

C++ P/Invoke:指针内存损坏

C++ P/Invoke:指针内存损坏,c++,mono,pinvoke,C++,Mono,Pinvoke,我正在用Mono(所以COM、CLI不是选项)和一堆extern包装fbxsdk的一部分(封闭的,带有公共API),在我不得不返回一个非指针实例之前,一切都进行得很顺利 重要的是我必须把它再返回给C++来进行另一个调用。因为我不知道没有指针你会怎么做,所以我返回了它: FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj) { return &obj->GetFirstProperty(); } …直到我尝试

我正在用Mono(所以COM、CLI不是选项)和一堆extern包装fbxsdk的一部分(封闭的,带有公共API),在我不得不返回一个非指针实例之前,一切都进行得很顺利

重要的是我必须把它再返回给C++来进行另一个调用。因为我不知道没有指针你会怎么做,所以我返回了它:

FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
    return &obj->GetFirstProperty();
}
…直到我尝试下一个代码片段,我才收到“System.AccessViolationException:尝试读取或写入受保护的内存。这通常表示其他内存已损坏”消息

如果我使用C++中相同的调用使用几乎相同的代码,那就没问题了。我用同样的方式又做了20次函数调用,但不需要“指针式”调用,它们也都很好,所以我不认为我的DllImport应该受到责备。那么,如果要责怪引用人,我该怎么做呢?我当然不会仅仅因为有人从API调用全局静态引用就将其存储在某个地方


非常感谢您的帮助,C/C++和它处理内存的显式方式对我来说是新的。

我假设您的程序正在崩溃,因为您获取指针的属性不再存在。让我澄清并从剖析以下内容开始:

FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
    return &obj->GetFirstProperty();
}
我查阅了FBX的文档,
FbxObject::GetFirstProperty()
的返回类型为
FbxProperty
。请注意,返回值不是任何指针或引用?这意味着您将得到一个所谓的“自动变量”,或者在本例中是一个“临时变量”。这种对象只会持续到您离开作用域为止,在本例中,作用域是包装器的
对象\u GetFirstProperty()
。之后,对象将被清理并从内存堆栈中移除
FbxObject::GetFirstProperty()
提供属性的副本,而不是实际引用。在内部,它可能不同,但是包装器关心的是属性对象本身,而不是它的内容

因此,您要做的是,当您稍后将地址传递给
属性时,会得到一个指向该地址的指针,该地址不再有效

在对象生命周期方面,C++的行为与C#不同。C++中的对象称为<代码> MyObj <代码>可以被认为是C++指针类型,如 MyObjult*/Cuth>——它就像一个参考值。在C++中,也有值类型,比如“代码>结构”<代码>等等,它们等价于C++自动变量。所有自动变量在其生存期范围结束时都会被销毁

要克服这个问题,您需要做的是直接保存从
FbxObject::GetFirstProperty()
获取的对象,而不是指向它的指针。基本上,您必须将对象打包成一个适当的.NET类,这样它的内容就不会丢失

或者,您可以只分配动态内存并将从
FbxObject::GetFirstPoperty()
获取的对象复制到那里,然后返回指向您自己内存的指针。当然,您以后必须手动删除此内存。下面是一个简单的例子:

FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
    // Allocate custom memory.
    char* myMem = new char[sizeof(FbxProperty)];

    // Copy the property's content there.
    std::memcpy(myMem, &obj->GetFirstProperty(), sizeof(FbxProperty));

    // Return custom memory address.
    return reinterpret_cast<FbxProperty*>(myMem);
}
但此尝试可能会导致其他问题,具体取决于实际的
FbxProperty
如何处理其内部数据。当然,您正在创建对象的副本,但是如果原始的temporaty/auto变量在销毁时删除了重要内存,那么您将遇到与现在类似的问题


如果你真的很聪明,你可以为你需要的每一种FBX类型编写真正的包装类,并对整个类类型进行马歇尔处理,而不是每次你想要得到一个值或属性时都必须调用单独的C函数。

我发现你的问题让人困惑:标题表明这个问题是关于非指针的返回值,然后继续解释如何需要返回指针。另外,问题是关于p/ujk,但是您只提供C++签名,而不是相应的C p/p/调用签名。我们不知道FbxProperty是什么。我们无法判断您返回的地址是否仍然有效。您没有显示任何c#。c++/CLI是否适合您?如果是这样的话,这是注定要在Windows上编写C#wrapper的;使用正确的P/Invoke可以为您省去所有的麻烦。感谢您的评论,我已经用新的问题标题澄清了这一点,并澄清了这是用于跨平台(mono)分发的,因此CLI不是一个选项-我希望是这样!
FBXAPI FbxProperty* Object_GetFirstProperty(FbxObject* obj)
{
    // Allocate custom memory.
    char* myMem = new char[sizeof(FbxProperty)];

    // Copy the property's content there.
    std::memcpy(myMem, &obj->GetFirstProperty(), sizeof(FbxProperty));

    // Return custom memory address.
    return reinterpret_cast<FbxProperty*>(myMem);
}
FBXAPI void Property_Free(FbxProperty* prop)
{
    // Free previously allocated memory
    delete[] prop;
}