Don';t了解gSOAP序列化过程中的错误

本文关键字:序列化 过程中 错误 gSOAP 了解 Don | 更新日期: 2023-09-27 18:23:58

在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’ed内存中),但在序列化步骤中,当我们结束web服务请求时,我遇到了访问冲突(即:我们的C++代码已发出SOAP_OK返回值,逻辑已返回到自动生成的gSOAP代码)。

当处理简单类型(int、long等)的数组时,整个过程运行得很好,但在处理更复杂的类型(类等)时会失败。

如果在ConvertArray方法中,我在第3行替换:

gSoapArray.__ptr = soap_new_ns__ContainerFile(soap, gSoapArray.__size);

为了分配内存,它运行良好。

所以,我不知道为什么。在第一种情况下,我使用soap_alloc来分配一个内存块,该内存块的大小相当于ContainerFile类的大小乘以托管数组中的元素数量。在第二种情况下,它可以归结为使用soap_new来做同样的事情。如果分配的内存都由gsoap管理,并且在其他方面是相同的(据我所知),那么为什么soap_alloc'ed版本在序列化过程中会失败?

使用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_embeded调用中失败了。我还应该注意,它在malloc'd块中的第一个元素上失败(即:当I==0时)。

Don';t了解gSOAP序列化过程中的错误

在C++中应该始终使用"new"而不是"malloc",如:

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没有初始化,所以动态方法调用会导致崩溃。