【问题标题】:Rapidjson document as a member variable crashes that applicationRapidjson 文档作为成员变量使该应用程序崩溃
【发布时间】:2014-05-13 12:52:35
【问题描述】:

当我使用 rapidjson 文档作为成员变量并这样做时:

class Test
{
     rapidjson::Document    m_jsonDocument;

public:
    void f()
    {
        // WORKS FINE
        rapidjson::Document document;
        if (document.Parse<0>("{ \"hello\" : \"world\" }").HasParseError())
            printf("ERROR PARSING JSON\n");
        else
            printf("%s\n", document["hello"].GetString());


         // BUT HERE THROWS, WHY?
         if (m_jsonDocument.Parse<0>("{ \"hello\" : \"world\" }").HasParseError())
             printf("ERROR PARSING JSON\n");
         else
            printf("%s\n", m_jsonDocument["hello"].GetString());
    }
};

当我调用 if (m_jsonDocument.Parse&lt;0&gt;("{ \"hello\" : \"world\" }").HasParseError()) 时,应用程序在 CTOR GenericValue(Type type) 中的 document.h 中的 flags_ = defaultFlags[type]; 在线崩溃。 Visual Studio 调试器显示“无法读取内存”。为_flags。问题是什么?成员变量和局部变量有什么区别?


编辑:我使用setResponseCallback defined heref 设置为回调,而f 正在使用dispatchResponseCallbacks defined here 作为回调调用。

【问题讨论】:

  • 函数f怎么调用?
  • @JoachimPileborg 调用服务器获取 JSON 数据,并且在响应到达时调用回调。 f 是回调函数。有关系吗?
  • @JoachimPileborg 哦,这真的很奇怪。我无法理解。我已按如下方式调用fTest t; t.f();,它起作用了。有什么不同?我该如何解决我的问题?

标签: c++ rapidjson


【解决方案1】:

问题很可能是,当调用成员函数指针f 时,它在没有实际对象的情况下被调用,这意味着成员函数中的this 指针无效。当您尝试访问成员变量时,这会导致undefined behavior,因为这些访问会隐式使用(无效的)this 指针。

有几种方法可以解决这个问题,最直接的方法是使用静态成员函数作为回调,并将对象的实例作为用户数据传递(大多数回调系统都允许这样做)。那么静态成员函数就可以使用用户数据对象指针来调用真正的函数了。

类似

class Test
{
    ...

public:
    static void f_wrapper(Test* object)
    {
        object->f();
    }
};

然后做例如

Test object;
set_callback(&Test::f_wrapper, &object);

注意object 不会超出范围。

【讨论】:

  • 我使用coco2d::network::HttpRequest,以防你熟悉这个。它有setResponseCallback,它接受两个参数:this 和一个指向方法的指针。 (该类应继承自 Layer 类。)当响应返回时,回调被调用如下:` if (pTarget && pSelector) { (pTarget->*pSelector)(this, response); }` 其中pTarget 是传递的thispSelector 是传递的方法。如您所见,它使用this 调用。
  • 另一件事我无法理解如果没有this,您如何调用非静态方法?
  • @Narek 如果您将&amp;Test::f 作为回调函数传递,调用您的函数的代码将愉快地调用Test::f,但它不知道这是一个非静态成员函数,因此会调用它作为一个普通函数,导致了这个问题。
  • @Narek 我还认为你需要编辑你的问题并添加更多代码来显示你在做什么,如果可能的话,Minimal, Complete, and Verifiable example
  • 但是调用是这样进行的:pTarget-&gt;*pSelector 相当于this-&gt;*pointerToF。不是说我用this打电话给f吗?
【解决方案2】:

正如@JoachimPileborg 所说,我如何称呼f(); 应该很重要,这是他详细解释的原因之一。感谢 Joachim 指引了正确的方向。实际上,我的问题比 Joachim 想象的更愚蠢 :)。问题是当对我的 HTTP 请求的响应返回时我正在调用 ff 是一个回调函数)。但就我在堆栈中分配Test t; 而言,因此内存被取消分配并且this 在响应返回时无效。我知道,这真的很愚蠢:)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 2017-06-04
    • 2014-04-28
    • 2012-04-15
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多