-2

異なる .cpp ファイル間で public/extern 構造体オブジェクトを宣言する際に問題があります。imgui ロガーを使用して、フックからいくつかのメッセージをログに記録しようとしています。

プログラムがクラッシュするExampleAppLog my_log2; -> ImGuiTextBuffer Buf; -> class ImVector -> if (Data)

ExampleAppLog* my_log2 = new ExampleAppLog();これは、構造体 ExampleAppLog を含む .h と my_log2 の宣言を含む .cpp 内で行うためです。

クラッシュする関連コード -> .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);
    }

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

1 に答える 1

0

重要な情報が欠落しているため、問題が何であるかを伝えるのは困難です。

  • Dataヌルポインターかどうかを確認中にクラッシュすることは確かですか?
  • thisクラッシュの時点で有効かどうかを確認しましたか?
  • コンストラクターにブレークポイントを設定して、いつ呼び出されたかを確認しましたか。

これらのオブジェクトのコピーを作成していないように見えますが、適切にサポートされていない場合は、コピーと移動のコンストラクターと代入演算子を削除して、コピーを防止することをお勧めします。詳細については、 https://en.cppreference.com/w/cpp/language/function#Deleted_functionsを参照してください。

問題が関数を作成する前に呼び出すことであるかどうかを確認する明白な方法の 1 つはExampleAppLog、コンストラクター内にブレークポイントを配置することです。上記のコードから、クラスが 1 回だけ作成されたのか、それとも (別の場所から) 複数回作成されたのかを確認することはできません。

また、オブジェクトを作成する前にDraworを呼び出さないでください。繰り返しになりますが、そのようなことはデバッガーでテストするのは簡単ですが、コードの一部だけを手にしていると判断するのは非常に困難です。実際、上記のプログラムにはがないため、MCVE ではありません。LookHookmy_log2main

オブジェクトを作成する前に使用しようとしたときではなく、オブジェクトを作成しているときに実際にクラッシュする場合ExampleAppLog、上記のコードのほとんどは役に立たず、コードをコメントアウトして(質問から削除して)それでもクラッシュする場合は、人々を大いに助けるでしょうあなたを助けること。

一方、作成前に my_log2 を使用しているためにクラッシュした場合は、問題を再現するために必要なコードが欠落しています。

問題が初期化順序に関連している場合は、シングルトンが解決策になる可能性があります。ここで受け入れられた回答を見てください: How to implement multithread safe singleton in C++11 without using <mutex>

いずれにせよ、あなたは質問に十分な努力を払っていないので、あなたを助けるのは難しい. コードを簡単にコピーして貼り付けることができない場合、重要な行や情報が欠落していることが明らかな場合でも、プロジェクトの作成に時間をかける人はほとんどいないことに注意してください。指定された行。

my_log2実際、main が空の関数であり、ポインターと構造体のグローバルな使用法が他にないと仮定するとExampleAppLog、関数はいつreserve呼び出されるでしょうか。

おまけとして、良い質問をすると、サイトでより多くのポイントを獲得できます!

于 2018-09-08T22:38:07.447 に答える