为什么我的 Thrift (c_glib) 客户端失败并出现 "invalid pointer" 错误?

Why does my Thrift (c_glib) client fail with an "invalid pointer" error?

我正在用 C (g_lib) 创建一个简单的节俭 server/client 程序。 这是我的 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 客户端的正确方法吗?我在这里做错了什么?

我发现您在这里所做的事情存在三个问题:

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

  • 尽管您不应该尝试修改 _return 的值,但是您的代码执行此操作的方式不正确,最终会破坏 [=10= 的数据结构] 点。这很可能解释了您看到的错误消息。

  • 您的代码声明 i 一个三十二位整数,但仅将 i 的第一个字节附加到字节数组。这不会对每个机器架构产生您想要的效果。

我花了一些时间才弄明白,这是工作处理程序和客户端实现代码:

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]);

  }