【问题标题】:Why does my Thrift (c_glib) client fail with an "invalid pointer" error?为什么我的 Thrift (c_glib) 客户端因“无效指针”错误而失败?
【发布时间】:2015-09-29 17:57:40
【问题描述】:

我正在用 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)

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

【问题讨论】:

    标签: c thrift glib


    【解决方案1】:

    我发现你在这里所做的三个问题:

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

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

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

    【讨论】:

    • 感谢西蒙的回复,请看内联问题::
    • 如果我只是 printf("%u\n", _return);它打印出 0,这意味着我猜该函数没有为它预先分配任何结构。现在,如果我自己分配一个 GByteArray (_return = g_byte_array_new ();) 用于返回,那么它似乎正在工作(至少没有崩溃)。我现在唯一遇到的问题是客户端没有接收到正确的数据。你可以在这里找到修改后的版本pastebin.com/HCwehPvR 此外,thrift 存储库不包含二进制数据的测试用例或示例。我想一旦我开始工作,我就可以将它添加到 repo 中。
    • 好!你是对的; binary 是基本类型,而不是复杂类型(即不是集合),所以我上面写的不正确。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-05
      • 2015-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-25
      • 2020-03-28
      相关资源
      最近更新 更多