为什么我的Thrift(c_glib)客户端因“无效指针”错误而失败?

时间:2015-09-23 13:21:48

标签: c thrift glib

我正在用C(g_lib)创建一个简单的thrift服务器/客户端程序。 这就是我的节俭IDL文件的样子:

namespace cpp tutorial

service Calculator {
    void ping(),
    binary getdata()    
}

thrift服务器上的getdata实现如下所示:

    static gboolean
    tutorial_calculator_handler_getdata (CalculatorIf  *iface,
                                      GByteArray        *_return,
                                      GError       **error)
    {
      THRIFT_UNUSED_VAR (iface);
      THRIFT_UNUSED_VAR (error);

      puts ("getdata()");

      GByteArray *gbarray;
      gint i;

      gbarray = g_byte_array_new ();
      for (i = 0; i < 100; i++)
          g_byte_array_append (gbarray, (guint8*) &i, 1);

      *_return = *gbarray;

      return TRUE;
    }

现在,在客户端,我按如下方式调用getdata:

....
....
GByteArray *data;
....
....

if (!error && calculator_if_getdata (client, &data, &error)) {
  puts ("getdata()");      

}

不幸的是,客户端在calculator_if_getdata调用中崩溃并显示以下消息:

*** Error in `./client': munmap_chunk(): invalid pointer: 0xb741742d ***
Aborted (core dumped)

这是在thrift中从服务器向客户端发送整数数组的正确方法吗?我在这做错了什么?

2 个答案:

答案 0 :(得分:0)

我看到你在这里做的三个问题:

  • 如果服务方法返回复杂类型,则传递给其处理函数的_return参数将指向预分配的结构,该结构不应被销毁或重新创建。您的代码应该将值附加到GByteArray已经指向的_return,而不是创建自己的GByteArray

  • 虽然您不应该尝试修改_return的值,但代码执行此操作的方式不正确,最终会破坏_return指向的数据结构。这很可能解释了您所看到的错误消息。

  • 您的代码声明i一个32位整数,但仅附加到字节数组i的第一个字节。这不会影响您对每个机器架构的影响。

答案 1 :(得分:0)

我花了一些时间在它上面想出来,这是工作处理程序和客户端实现代码:

gboolean 
tutorial_calculator_handler_getdata (CalculatorIf *iface,
                                 GByteArray ** _return,                                 
                                 GError **error)
{
  THRIFT_UNUSED_VAR (iface);
  THRIFT_UNUSED_VAR (error);

  GByteArray *thing = g_byte_array_new();
  *_return = g_byte_array_new();
  guint8 i;
  for (i = 0; i < 10; i++){    
    g_byte_array_append (thing, (guint8*) &i, sizeof(guint8));
  }

  g_byte_array_append(*_return, (guint8*) thing->data, thing->len);


  return TRUE;
}

客户方:

GByteArray *data = g_byte_array_new();
if (!error && calculator_if_getdata (client, &data, &error)) {
    puts ("getdata()");
    printf ("Data : %d\n", data);
    guint8 i;
    guint8 size = sizeof(guint8);
    for(i=0;i<10;i++)
      printf ("Data : %d\n", data->data[size*i]);

  }