Json-Glib 对象插入时跳转无效

Json-Glib Invalid jumps on object insertions

我正在使用 C 语言 Json 库,即 Json-Glib。 问题是图书馆一直在对我进行段错误,我不明白为什么。我阅读了所有文档,了解到根节点可以包含一些原始值,但更重要的是一个对象。我正在尝试实现一个对象串联,但是当我尝试将一个对象放入一个节点中,或者甚至只是在其中添加字符串成员时,我得到无效跳转作为通常大小 8(string) 的无效读取。 这是试图从 Json 节点检索 Json 对象的代码,因为在检索到的 Json 对象中插入少量字符串。

int main(){

    const gchar *auth = "authentication";

    //here i initialize my Root JsonNode with an object in it and a JsonObject to be able to get the object from the JsonNode                           
    JsonObject* authObject = json_object_new();
    JsonNode* extNode = json_node_new(JSON_NODE_OBJECT);

    // Here i retrieve the initialized JsonObject that is inside my JsonNode                                                                            
    authObject = json_node_get_object(extNode);

    // And here some few insertion of strings in the object                                                                                             
    SegFault Here -> json_object_set_string_member(authObject, "action", "authenticate");
    json_object_set_string_member(authObject, "type", "authType");
    json_object_set_string_member(authObject, "resource", "resource");
    json_object_set_string_member(authObject, "version", "none");
    json_object_set_string_member(authObject, "data", "loginData");

    //here i try to print my json file but i can't even reach this execution line due to SegFault                                                       
    char* toto = cometd_json_node2str(extNode);
    puts(toto);

    return 0;
}

这是 Valgrind 报告:

==4910== Memcheck, a memory error detector
==4910== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4910== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info
==4910== Command: ./a.out
==4910== 
==4910== Invalid read of size 8
==4910==    at 0x10013C28D: json_object_set_string_member (in /usr/local/Cellar/json-glib/1.0.2/lib/libjson-glib-1.0.0.dylib)
==4910==    by 0x100000DD1: main (main.c:50)
==4910==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==4910== 
==4910== 
==4910== Process terminating with default action of signal 11 (SIGSEGV)
==4910==  Access not within mapped region at address 0x0
==4910==    at 0x10013C28D: json_object_set_string_member (in /usr/local/Cellar/json-glib/1.0.2/lib/libjson-glib-1.0.0.dylib)
==4910==    by 0x100000DD1: main (main.c:50)
==4910==  If you believe this happened as a result of a stack
==4910==  overflow in your program's main thread (unlikely but
==4910==  possible), you can try to increase the size of the
==4910==  main thread stack using the --main-stacksize= flag.
==4910==  The main thread stack size used in this run was 8388608.
==4910== 
==4910== HEAP SUMMARY:
==4910==     in use at exit: 836,054 bytes in 2,098 blocks
==4910==   total heap usage: 2,577 allocs, 479 frees, 1,410,814 bytes allocated
==4910== 
==4910== LEAK SUMMARY:
==4910==    definitely lost: 3,167 bytes in 45 blocks
==4910==    indirectly lost: 5,357 bytes in 22 blocks
==4910==      possibly lost: 20,836 bytes in 214 blocks
==4910==    still reachable: 128,596 bytes in 853 blocks
==4910==         suppressed: 678,098 bytes in 964 blocks
==4910== Rerun with --leak-check=full to see details of leaked memory
==4910== 
==4910== For counts of detected and suppressed errors, rerun with: -v
==4910== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 1 from 1)

任何帮助将不胜感激,事实上,如果我可以调试它,我会写一篇关于 Json-Glib 的教程,以帮助其他程序员不为它苦苦挣扎。

您正在覆盖 authObject 指针:

JsonObject* authObject = json_object_new(); // ← You create it here…
JsonNode* extNode = json_node_new(JSON_NODE_OBJECT);

authObject = json_node_get_object(extNode); // ← … but overwrite it here

在新创建的 JsonNode 上调用 json_node_get_object() 将 return NULL,因为您尚未设置对象。

如果你想用对象设置 JsonNode,请改用 json_node_init_object()

JsonObject *authObject = json_object_new ();
JsonNode *node = json_node_init_object (json_node_alloc (), authObject);

或使用json_node_new()json_node_take_object():

JsonObject *authObject = json_object_new ();
JsonNode *node = json_node_new (JSON_NODE_OBJECT);
json_node_take_object (node, authObject);

现在您可以添加成员到 authObject

以下是我如何应用 ebassi 先生的回答。更一般地说,我是如何让它发挥作用的。

cometd_new_handshake_message(const cometd* h)
{

  gint64 seed = ++(h->conn->msg_id_seed);


  /////////////////Data Concatenation/////////////                                                                                                                                                                                                                                                                             

  JsonObject* dataObject = json_object_new();
  JsonNode*   dataNode = json_node_new(JSON_NODE_OBJECT); JsonNode*   dataRoot = json_node_init_object(dataNode, dataObject);

  dataObject = json_node_get_object(dataRoot);

  json_object_set_string_member(dataObject, "login", "test2");
  json_object_set_string_member(dataObject, "password", "password");

  ////////////////Data Concatenation////////////                                                                                                                                                                                                                                                                               

  /////////////////Auth/////////////////                                                                                                                                                                                                                                                                                       

  // I begin from the most inner JsonObject of my Json File                                                                                                                                                                                                                                                                    

  //here i initialize my Root JsonNode with an object in it and a JsonObject to be able to get the object from the JsonNode                                                                                                                                                                                                    

  JsonObject* authObject = json_object_new();
  JsonNode*   authNode = json_node_new(JSON_NODE_OBJECT);
  JsonNode*   authRoot = json_node_init_object(authNode, authObject);

  // Here i retrieve the initialized JsonObject that is inside my JsonNode                                                                                                                                                                                                                                                     
  authObject = json_node_get_object(authRoot);

  // And here some few insertion of strings in the object                                                                                                                                                                                                                                                                      
  json_object_set_string_member(authObject, "action", "authenticate");
  json_object_set_string_member(authObject, "type", "GmY-HuzW.KZyH.simple");
  json_object_set_string_member(authObject, "resource", "zetapushTuto");
  json_object_set_member(authObject, "data", dataRoot);

  ///////////////Auth/////////////////                                                                                                                                                                                                                                                                                         



  //////////////First Concatenation : Authentication///////////////                                                                                                                                                                                                                                                            
  //Here i make the authentication of my first JsonObject with a upper membrane.                                                                                                                                                                                                                                               

  JsonObject *extMembrane = json_object_new();
  JsonNode   *contactMembrane = json_node_new(JSON_NODE_OBJECT);  JsonNode   *secondRootMembrane = json_node_init_object(contactMembrane, extMembrane);

  extMembrane = json_node_get_object(secondRootMembrane);

  json_object_set_member(extMembrane, "authentication", authRoot);
  /////////////First Concatenation////////////////                                                                                                                                                                                                                                                                             

  ////////////Second Concatenation : Ext///////////////                                                                                                                                                                                                                                                                        
  // Here i finnaly concatenante my last JsonObject and encapsulate the overall file inside the root JsonNode                                                                                                                                                                                                                  
  JsonObject *rootObjectMembrane = json_object_new();
  JsonNode   *initRootMembrane = json_node_new(JSON_NODE_OBJECT);
  JsonNode   *rootMembrane = json_node_init_object(initRootMembrane, rootObjectMembrane);

   rootObjectMembrane = json_node_get_object(rootMembrane);

   json_object_set_member(rootObjectMembrane, "ext", secondRootMembrane);


  // I still needs to create a object under Ext JsonNode, then an JsonArray to supportedConnectionTypes                                                                                                                                                                                                                        
  //Then add the advice object with "timeout" and "interval"                                                                                                                                                                                                                                                                   

  json_object_set_int_member(rootObjectMembrane, "id", seed);
  json_object_set_string_member(rootObjectMembrane, "version", "1.0");
  json_object_set_string_member(rootObjectMembrane, "minimumVersion", "1.0");
  json_object_set_string_member(rootObjectMembrane, "channel", "/meta/handshake");

  JsonArray* json_transports = json_array_new();
  GList* entry = h->config->transports;
  while (entry){
    cometd_transport* t = entry->data;
    json_array_add_string_element(json_transports, t->name);
    entry = g_list_next(entry);
}

  //json_array_add_string_element(json_transports, "long-polling");                                                                                                                                                                                                                                                            
  json_object_set_array_member(rootObjectMembrane, "supportedConnectionTypes", json_transports);

  //////////Advice////////                                                                                                                                                                                                                                                                                                     
  JsonObject *adviceMembrane = json_object_new();
  JsonNode   *adviceNodeMembrane = json_node_new(JSON_NODE_OBJECT);
  JsonNode   *adviceRootMembrane = json_node_init_object(adviceNodeMembrane, adviceMembrane);
  gint64 interval = 0;
  gint64 timeout = 60000;
  adviceMembrane = json_node_get_object(adviceRootMembrane);
  json_object_set_int_member(adviceMembrane, "timeout", timeout);
  json_object_set_int_member(adviceMembrane, "interval", interval);
  json_object_set_member(rootObjectMembrane, "advice", adviceRootMembrane);

  /////////Advice////////                                                                                                                                                                                                                                                                                                      



   ////////////Second Concatenation//////////////                                                                                                                                                                                                                                                                              

  // call extensions with message - TODO: implement extensions first                                                                                                                                                                                                                                                           
  //json_node_take_object(root, obj);                                                                                                                                                                                                                                                                                          
  return rootMembrane;
}