gsoap为动态结构数组分配内存。

时间:2018-09-12 17:34:45

标签: c memory malloc gsoap

gSoap有效地创建存根以帮助进行内存管理等。其中之一 命令是soap_malloc,但似乎没有相应的soap_realloc。 在开始编写自己的push和pop方法之前,我只想确保自己没有遗漏任何明显的东西。

//example.h generated with wsdl2h

struct ns1___Customer
{
    int   __sizeProduct;     
    ns1__Product *Product;        
    int  customerid;       
}

struct ns1__Product
{
    int  productid;
}

我当前正在使用soap_malloc,然后重新分配以动态增长数组。

//I could use soap_new_ns1__Product(&soap,XXX) and allocate mem for XXX
//number of ns1__Product structures but this is wasteful and doesn't solve 
//anything

struct ns1__Customter cust;
soap_default_ns1__Product(soap, &cust);

struct ns1__Product *prod_array = NULL;

//allocate mem for 1 product
prod_array = soap_new_ns1__Product(soap,1) ;

soap_default_ns1__Product(soap, &prod_array[0]);
prod_array[0].productid=111;

//Need to add product therefore need to realloc mem. 
//IS THIS THE BEST WAY IN gsoap?
prod_array = realloc( prod_array, 2 * sizeof(struct  ns1__Product)) ;
soap_default_ns1__Product(soap, &emp_array[1]);
prod_array[1].product=222;

//assigning array ptr to Customer
cust.Product=prod_array;
// Remember to adjust sizeProduct
cust.__sizeProduct=2;

这似乎是错误且笨拙的,gsoap是否建议一种更好的方法?我在文档中或通过在线搜索找不到清晰的示例。

2 个答案:

答案 0 :(得分:1)

  

在我开始编写自己的push和pop方法之前,我只是想确保自己没有遗漏任何明显的东西。

我怀疑您缺少soap_malloc()分配的内存至少在某些情况下会自动释放的。因此,使用realloc()来调整分配的内存大小很麻烦。这样的重新分配很有可能会成功,但是当gSOAP的自动释放尝试插入soap_end()时,您至少最终会陷入麻烦。

另一方面,我认为您不会忽略任何重新分配功能。 The docs确实似乎没有描述任何东西。您始终可以实现自己的重新分配包装器,该包装器使用soap_malloc()分配新的内存,复制原始空间的内容(您需要某种方式知道其大小),然后使用soap_dealloc()释放原始空间。

底线似乎是soap_malloc()并非旨在用作通用分配器,它并不是特别适合您的用例。它的主要目标似乎是内部的,目的是使库用户无需手动释放库分配的临时对象。我将其公开给图书馆用户以供他们直接使用,目的是为了方便。

如果您希望能够重新分配块,那么我建议您首先通过常规malloc()获得它们。如果您要混合malloc()个数据和soap_malloc()个数据,则需要仔细阅读文档,但这是可能的。或者,考虑不需要重新分配的方法,例如将数据存储在链接列表中,而不是动态数组中。

答案 1 :(得分:0)

您在那里所做的确实是错误的。使用soap_new_T()(在您的情况下,Tns1__Product)之后,soap上下文现在通过内部保持ns1__Product*指针来管理该内存。稍后,当您调用soap_destroy()释放由soap_new_T()上下文管理的所有soap分配的对象时,该上下文将尝试释放自您调用以来不再指向有效内存的指针realloc()

就像John Bollinger pointed out一样,gSOAP中没有内置的方法来做类似于realloc的事情。相反,您只需要手动进行重新分配,例如:

// allocate memory for 1 product (as you already do above)
prod_array = soap_new_ns1__Product(soap, 1);

// ... do some stuff, realize you need to "realloc" to add another product ...

// allocate a new array, managed by the soap context
struct ns1__Product* new_array = soap_new_ns1__Product(soap, 2);

// copy the old array into the new one (assuming old_size is however many elements are in prod_array)
for(std::size_t i = 0; i < old_size; ++i)
{
    new_array[i] = prod_array[i];
}

// tell the soap context to destroy the old array
soap_dealloc(soap, prod_array);

在旁边:

似乎应该可以使用std::vector<ns1__Product>而不是数组,这将以更好的方式解决您的问题,但是该问题已经被here要求无效。不幸的是,我目前不知道答案。