【问题标题】:C++ - gsoap : Parameter passing memory management issuesC++ - gsoap:参数传递内存管理问题
【发布时间】:2008-12-22 19:48:34
【问题描述】:

我正在为它编写一个 Web 服务器和客户端测试存根。我对参数的内存管理有疑问。

我正在从我的客户调用一个肥皂函数 ns1_func1(input * pInput, output* pOutput) 现在输入和输出类都包含指向其他结构的指针。

例如

类输出 { 类 abc * p1; 类定义 * p2; };

我的问题是 - 谁负责内存分配?客户端负责输入内存分配,服务器负责输出内存管理吗?

现在我的客户端代码看起来像这样

client_fn()
{

 ...

 input inp1;
 output * pOutput = NULL;
 ns1_func1(&inp1, pOutput);
 if(pOutput == NULL)
 {
   cout<<"pOut is NULL\n";
   return ERR;
 }
 else
 {
   // retrive output values from pOutput
 }

 ...
}

尽管使用 soap_new_Output(soap, -1) 从服务器分配 pOutput,但在调用 ns1_func1 后,我总是将 pOutput 设为 NULL。

另外,我的理解是我们应该使用soap_new_X 来分配内存,当我们调用soap_destroy 时它会自动释放。如果我错了,请纠正我。

基本上,我不知道在这种情况下应该由谁来处理内存分配/释放。

任何帮助都会很棒。

【问题讨论】:

    标签: c++ web-services memory-management soap gsoap


    【解决方案1】:

    因为客户端和服务器一般是不同的进程,或者不同的机器,它们各自负责各自的内存管理。客户端必须为其输入参数分配内存,然后 gsoap 将其序列化以发送到服务器。

    服务器反序列化输入参数,分配它需要的任何内存。它为其输出分配内存,gsoap 将其序列化以发送回客户端。客户端反序列化服务器的响应,分配它需要的任何内存。

    您肯定需要使用soap_malloc(等)进行内存分配,这是gsoap 库可以跟踪SOAP 调用清理时需要释放的唯一方法。

    在您给出的特定 ns1_func1 示例中,服务器分配响应,并且生成的客户端代码应该分配它需要的任何内存。该调用的 WSDL 中可能有问题,生成的客户端代码不是您所期望的。

    【讨论】:

      【解决方案2】:

      谢谢丹顿,

      我面临的问题是,在服务器中,我使用soap_new_abc 和soap_new_def 为类abc 和def 分配内存。这些在清理过程中不会被释放。在清理部分,我调用了soap_destroy、soap_end 和soap_free。根据 gsoap 文档,soap_free 应该调用通过 soap_new_X 分配的类的 ~tors ,但这并没有发生。我实际上将 DEBUG 语句放在了 soapC.cpp 中的 ctors 和 ~tors 中。 ctor 中的 DEBUG 语句出现了,但 ~tors 中没有。所以我担心可能存在内存泄漏。

      soap_delete_X 不应该在从soap_free 清理期间自动调用吗?

      【讨论】:

      • 一旦您返回 SOAP_OK,您分配的任何内容都无法控制,因此所有这些关于 soap_end() 或 soap_destroy() 的明显胡言乱语充其量只是理论上的。如果我必须跟踪我分配的内存并在下一次“结束”或“销毁”它,这似乎违背了 soap_new_T() 的目的。如果您想讨论幕后发生的事情,无论您是否引用了令人困惑的 Genivia 文档,都不要在混淆用户责任问题的地方讨论!
      • 我无法在 5 分钟内编辑评论,因为其中有 10 分钟用于删除单词之间的空格以使其适合!简而言之,我想说的是,不要将问题与对soap_end() 等的多余理论调用混为一谈,这不是你的责任!!!
      【解决方案3】:

      ns1_func1 的签名是什么?是 ns1_func1( Input*, Output*) 还是 ns1_func1( Input*, Output*& ) ?对于第一种情况,您将永远无法获得非空值。

      【讨论】:

        【解决方案4】:

        执行此代码后:

        output * pOutput = NULL;
        ns1_func1(&inp1, pOutput);
        

        pOutput 将始终为 NULL,无论 ns1_func 做什么。您将 pOutput 的 值 传递给函数,在本例中为 NULL。如果不知道 pOutput 的 地址(写成 &pOutput),该函数无法更改该值。

        ns1_func1 请求一个指向“输出”结构的指针,因为这是它想要写入输出数据的地方。这意味着您需要在堆栈上分配该空间:

        output theOutput;
        output * pOutput = &theOutput;
        ns1_func1(&inp1, pOutput);
        

        或在堆上:

        output * pOutput = malloc(sizeof(output));
        ns1_func1(&inp1, pOutput);
        ...
        free(pOutput);
        

        如果 ns1_func1 为你分配内存,它必须返回一个指向输出结构的指针。为此,它需要询问该指针的地址,或指向指针的指针。换句话说,像这样的声明:

        output * pOutput = NULL;
        different_ns1_func1(&inp1, &pOutput);
        if (pOutput != NULL) {
            ...
            free(pOutput);
        }
        

        对不起,如果这有点令人困惑,所有关于指针的讨论,但你问题的基本答案是 你 必须为函数分配内存来写入,因为函数正在询问 数据的地址,而不是 指向数据的指针的地址。

        【讨论】:

          猜你喜欢
          • 2013-03-21
          • 2012-07-23
          • 2011-05-11
          • 2011-03-13
          • 1970-01-01
          • 1970-01-01
          • 2018-03-31
          • 2015-12-09
          相关资源
          最近更新 更多