在Windows,C#和托管C ++上使用gSoap 2.7.17。
我有(gSOAP)类描述文件数组:
class ns__ContainerFile
{
public:
xsd__long fileId;
xsd__string fileName;
};
class ContainerFileArray
{
public:
ns__ContainerFile *__ptr;
int __size;
};
class ns__Container
{
public:
xsd__long containerId 0:1 = 0;
xsd__string name 0:1 = "";
xsd__string description 0:1 = "";
ContainerFileArray* files 0:1 = NULL;
};
在托管c ++中,我分配了返回数组:
ContainerFileArray gSoapArray;
gSoapArray.__size = managedArray->Length;
gSoapArray.__ptr = (ns__ContainerFile*) soap_malloc(soap, sizeof(ns__ContainerFile) * gSoapArray.__size);
上面的代码是名为ConvertArray的方法的一部分,因此被调用:
ns__Container unManaged;
*unManaged.files = ConvertArray(soap, managed->files->ToArray());
问题是,虽然ConvertArray似乎运行正常(我可以看到数据元素看似正确地填充在malloc的内存中),但是当我们整理Web服务时,我在序列化步骤中遇到访问冲突请求(即:我们的C ++代码已发出SOAP_OK返回值,逻辑已返回到自动生成的gSOAP代码)。
当处理简单类型的数组时,整个过程工作正常 - 整数,长整数等,但是会出现更复杂的类型 - 类等。
如果在ConvertArray方法中,我替换第3行:
gSoapArray.__ptr = soap_new_ns__ContainerFile(soap, gSoapArray.__size);
分配内存,它工作正常。
所以,我不确定我理解为什么。在第一种情况下,我使用soap_malloc来分配一个ContainerFile类大小的内存块,但是托管数组中有许多元素。在第二种情况下,它归结为使用soap_new做同样的事情。如果分配的内存全部由gsoap管理,并且在其他方面是相同的(据我所知),为什么soap_malloc的版本在序列化期间会失败?
使用Visual Studio,我可以看到它在以下生成的代码中失败:
void ContainerFileArray::soap_serialize(struct soap *soap) const
{
if (this->__ptr && !soap_array_reference(soap, this, (struct soap_array*)&this->__ptr, 1, SOAP_TYPE_ContainerFileArray))
for (int i = 0; i < this->__size; i++)
{ soap_embedded(soap, this->__ptr + i, SOAP_TYPE_IDCXDService__ContainerFile);
this->__ptr[i].soap_serialize(soap);
}
}
指示符位于突出显示的行上,但我怀疑它在soap_embedded调用中失败了。我还应该注意,它在malloc'd块中的第一个元素上失败了(即:当i == 0时)。
答案 0 :(得分:0)
你应该经常使用&#39; new&#39;而不是&#39; malloc&#39;在C ++中,如:
gSoapArray.__ptr = soap_new_ ns__ContainerFile(soap, gSoapArray.__size);
或者甚至更好,在gSOAP头文件中使用STL std :: vector,如下所示:
#import "stlvector.h"
class ns__Container
{
public:
xsd__long containerId 0:1 = 0;
xsd__string name 0:1 = "";
xsd__string description 0:1 = "";
std::vector<ns__ContainerFile> files 0:1 = NULL;
};
基本上,malloc在C ++中不安全,因为实例的VMT未初始化,因此动态方法调用会导致崩溃。