-2

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

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

因为我ExampleAppLog* my_log2 = new ExampleAppLog();在一个包含 .h 的 .cpp 中执行此操作,其中包含 struct 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;

一.cpp

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

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

二.cpp

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

我尝试了许多不同的方法,但没有运气,但在尝试在多个 .cpp 中共享外部对象时不会崩溃。

记录器文档。

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");
4

1 回答 1

0

很难告诉您您的问题是什么,因为缺少重要信息。

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

虽然看起来您没有制作这些对象的任何副本,但如果通过删除复制和移动构造函数和赋值运算符没有得到适当的支持,最好防止它发生。有关详细信息,请参阅https://en.cppreference.com/w/cpp/language/function#Deleted_functions

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

你也确定你不打电话DrawLookHook在你创建my_log2对象之前。再一次,这种事情用调试器测试是微不足道的,但对于我们来说,只用我们手中的部分代码就很难说出来。实际上,由于上​​述程序没有main,因此它不是 MCVE。

如果它在创建ExampleAppLog对象时确实崩溃,而不是在创建对象之前尝试使用它时,那么上面的大部分代码都是无用的,如果它仍然崩溃,注释掉代码(并将其从问题中删除),将对人们有很大帮助来帮助你。

另一方面,如果它因为在创建之前使用 my_log2 而崩溃,则缺少一些重现问题所需的代码。

如果问题与初始化顺序有关,那么单例可能是解决方案。在这里查看接受的答案:How to implement multithread safe singleton in C++11 without using <mutex>

无论如何,很难帮助你,因为你没有在你的问题上付出足够的努力。请记住,如果代码不能轻易复制和粘贴,几乎没有人会花时间创建一个项目,甚至当重要的行或信息明显丢失时,因为使用提供的信息,它几乎不可能在指定的行。

事实上,在我们假设 main 是一个空函数并且my_log2指针和ExampleAppLog结构都没有其他全局使用时,那么何时reserve调用该函数。

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

于 2018-09-08T22:38:07.447 回答