在两个.cpp文件之间定义全局类/结构指针

时间:2018-09-08 15:43:55

标签: c++ class pointers struct imgui

我在声明不同.cpp文件之间的public / extern结构对象时遇到问题。我正在尝试使用imgui记录器从挂钩中记录一些消息。

程序将在ExampleAppLog my_log2; -> ImGuiTextBuffer Buf; -> class ImVector -> if (Data)上崩溃

因为我是在.cpp中执行此ExampleAppLog* my_log2 = new ExampleAppLog();的工作,因此其中包含一个包含.h的结构体ExampleAppLog以及一个my_log2声明。

要崩溃的相关代码-> .h

struct ExampleAppLog
    {
        ImGuiTextBuffer     Buf;
    }
extern ExampleAppLog* my_log2;

.cpp

 #include ".h"
 ExampleAppLog* my_log2 = new ExampleAppLog(); //this line make it crash

imgui.h

struct ImGuiTextBuffer
{
    ImVector<char>      Buf;
}

class ImVector
{
public:
    int                         Size;
    int                         Capacity;
    T*                          Data;

    typedef T                   value_type;
    typedef value_type*         iterator;
    typedef const value_type*   const_iterator;

    ImVector()                  { Size = Capacity = 0; Data = NULL; }
    ~ImVector()                 { if (Data) ImGui::MemFree(Data); }

    inline bool                 empty() const                   { return Size == 0; }
    inline int                  size() const                    { return Size; }
    inline int                  capacity() const                { return Capacity; }

    inline value_type&          operator[](int i)               { IM_ASSERT(i < Size); return Data[i]; }
    inline const value_type&    operator[](int i) const         { IM_ASSERT(i < Size); return Data[i]; }

    inline void                 clear()                         { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }
    inline iterator             begin()                         { return Data; }
    inline const_iterator       begin() const                   { return Data; }
    inline iterator             end()                           { return Data + Size; }
    inline const_iterator       end() const                     { return Data + Size; }
    inline value_type&          front()                         { IM_ASSERT(Size > 0); return Data[0]; }
    inline const value_type&    front() const                   { IM_ASSERT(Size > 0); return Data[0]; }
    inline value_type&          back()                          { IM_ASSERT(Size > 0); return Data[Size-1]; }
    inline const value_type&    back() const                    { IM_ASSERT(Size > 0); return Data[Size-1]; }
    inline void                 swap(ImVector<T>& rhs)          { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }

    inline int                  _grow_capacity(int size) const  { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > size ? new_capacity : size; }

    inline void                 resize(int new_size)            { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; }
    inline void                 resize(int new_size, const T& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; }
    inline void                 reserve(int new_capacity)
    {
        if (new_capacity <= Capacity) return;
        T* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(T));
        if (Data) //here is the crash. Data is 0x000000000 when crashing
            memcpy(new_data, Data, (size_t)Size * sizeof(T));
        ImGui::MemFree(Data);
};

示例代码-> .h

struct ExampleAppLog
{
    ImGuiTextBuffer     Buf;
    ImGuiTextFilter     Filter;
    ImVector<int>       LineOffsets;        // Index to lines offset
    bool                ScrollToBottom;

    void    Clear() { Buf.clear(); LineOffsets.clear(); }

    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
    {
        int old_size = Buf.size();
        va_list args;
        va_start(args, fmt);
        Buf.appendv(fmt, args);
        va_end(args);
        for (int new_size = Buf.size(); old_size < new_size; old_size++)
            if (Buf[old_size] == '\n')
                LineOffsets.push_back(old_size);
        ScrollToBottom = true;
    }

    void    Draw(const char* title, bool* p_open = NULL)
    {
        ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
        ImGui::Begin(title, p_open);
        if (ImGui::Button("Clear")) Clear();
        ImGui::SameLine();
        bool copy = ImGui::Button("Copy");
        ImGui::SameLine();
        Filter.Draw("Filter", -100.0f);
        ImGui::Separator();
        ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
        if (copy) ImGui::LogToClipboard();

        if (Filter.IsActive())
        {
            const char* buf_begin = Buf.begin();
            const char* line = buf_begin;
            for (int line_no = 0; line != NULL; line_no++)
            {
                const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
                if (Filter.PassFilter(line, line_end))
                    ImGui::TextUnformatted(line, line_end);
                line = line_end && line_end[1] ? line_end + 1 : NULL;
            }
        }
        else
        {
            ImGui::TextUnformatted(Buf.begin());
        }

        if (ScrollToBottom)
            ImGui::SetScrollHere(1.0f);
        ScrollToBottom = false;
        ImGui::EndChild();
        ImGui::End();
        }
    }; 


extern ExampleAppLog* my_log2;

One.cpp

#include ".h"
        ExampleAppLog* my_log2 = new ExampleAppLog(); //this line make it crash

       void LogHook(const char* Info)
    {
        my_log2->AddLog(Info);
    }

Two.cpp

#include ".h"
    bool bDraw = true;
    void Draw()
    {
      my_log2->Draw("Logger", &bDraw);
    }

我尝试了许多不同的方法,但是没有成功,如果尝试在多个.cpp中共享一个extern对象,它最终会崩溃。

记录器文档。

static ExampleAppLog my_log; //have tryd this but with extern etc. It still crash at the same place whan trying to share it globaly. If i do it all in one .cpp out sharing it publicly the code work
[...]
my_log.AddLog("Hello %d world\n", 123);
[...]
my_log.Draw("title");

1 个答案:

答案 0 :(得分:0)

由于缺少重要信息,很难告诉您问题出在哪里。

  • 您确定在检查Data是否为空指针时崩溃吗?
  • 您是否已检查this在崩溃时是否有效?
  • 您是否在构造函数上放置了一个断点,以查看何时调用它。

虽然您似乎没有对这些对象进行任何复制,但是如果不能通过删除复制并移动构造函数和赋值运算符来提供适当的支持,则最好防止该复制。有关更多信息,请参见https://en.cppreference.com/w/cpp/language/function#Deleted_functions

一种明显的查看问题的方法是在创建ExampleAppLog之前调用一个函数,即在构造函数中放置一个断点。从上面的代码中,我们无法确定该类是仅一次创建还是多次创建(从其他位置)。

您还确定在创建Draw对象之前不要调用LookHookmy_log2。再说一遍,用调试器进行测试是一件很简单的事情,但是对于我们来说,只用部分代码很难讲。实际上,由于上​​述程序没有main,因此它不是MCVE。

如果创建ExampleAppLog对象时确实崩溃了,而不是在创建对象之前尝试使用它,那么上面的大多数代码是无用的,并且注释掉了代码(并将其从问题中删除),如果它仍然崩溃,将极大地帮助人们为您提供帮助。

另一方面,如果由于在创建my_log2之前使用了my_log2而导致崩溃,则缺少一些重现此问题所需的代码。

如果问题与初始化顺序有关,则可能是单例。在此处查看已接受的答案:How to implement multithread safe singleton in C++11 without using <mutex>

在任何情况下,都很难为您提供帮助,因为您在问题上的投入不足。请记住,如果无法轻松地复制和粘贴代码,则在明显缺少重要的行或信息的情况下,几乎没有人会花更多的时间来创建项目,因为有了所提供的信息,它几乎不可能崩溃。指定的行。

实际上,我们假设main是一个空函数,并且my_log2指针和ExampleAppLog结构都没有其他全局用法,那么函数reserve何时会成为叫。

作为奖励,如果您提出好的问题,则可以在网站上获得更多积分!