在两个 .cpp 文件之间定义全局 class/struct 指针
Defining global class/struct pointer between two .cpp files
我在不同的 .cpp 文件之间声明 public/extern 结构对象时遇到问题。我正在尝试使用 imgui 记录器从钩子中记录一些消息。
程序将在 ExampleAppLog my_log2; -> ImGuiTextBuffer Buf; -> class ImVector -> if (Data)
崩溃
因为我在一个 .cpp 中执行此操作 ExampleAppLog* my_log2 = new ExampleAppLog();
,其中包含包含 .h 的 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;
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 中共享一个外部对象时,如果没有崩溃,我就不走运了。
记录器文档。
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");
很难告诉您您的问题是什么,因为缺少重要信息。
- 您确定它在检查
Data
是否为空指针时崩溃了吗?
- 您是否检查过
this
在崩溃时是否有效?
- 你有没有在构造函数上打断点,看看什么时候调用的。
虽然看起来您没有制作这些对象的任何副本,但如果没有适当的支持,最好通过删除复制和移动构造函数和赋值运算符来阻止它。有关详细信息,请参阅 https://en.cppreference.com/w/cpp/language/function#Deleted_functions。
查看问题是否是您在创建 ExampleAppLog
的函数之前调用它的一个明显方法是在构造函数中放置一个断点。从上面的代码中,我们无法确定 class 是只创建一次还是多次(从其他地方创建)。
此外,您确定在创建 my_log2
对象之前没有调用 Draw
或 LookHook
。同样,这种事情用调试器测试是微不足道的,但我们很难用手中的部分代码来判断。事实上,由于上面的程序没有 main
,它不是 MCVE。
如果它真的在创建 ExampleAppLog
对象时崩溃,而不是在创建之前尝试使用它时崩溃,那么上面的大部分代码都是无用的并且注释掉代码(并将其从问题中删除) 如果它仍然崩溃,将极大地帮助人们帮助你。
另一方面,如果它因为您在创建它之前使用 my_log2 而崩溃,则说明缺少重现该问题所需的一些代码。
如果问题与初始化顺序有关,那么单例可能是解决方案。在此处查看已接受的答案:How to implement multithread safe singleton in C++11 without using <mutex>.
不管怎么说,都很难帮到你,因为你的问题不够用心。请记住,如果代码不能轻易复制和粘贴,几乎没有人会花更多的时间来创建项目,因为很明显缺少重要的行或信息,因为根据提供的信息,它几乎不可能崩溃指定行。
事实上,我们假设 main 是一个空函数,并且 my_log2
指针和 ExampleAppLog
结构没有其他全局用法,那么函数 reserve
被调用。
作为奖励,如果您提出好的问题,您会在网站上获得更多积分!
我在不同的 .cpp 文件之间声明 public/extern 结构对象时遇到问题。我正在尝试使用 imgui 记录器从钩子中记录一些消息。
程序将在 ExampleAppLog my_log2; -> ImGuiTextBuffer Buf; -> class ImVector -> if (Data)
因为我在一个 .cpp 中执行此操作 ExampleAppLog* my_log2 = new ExampleAppLog();
,其中包含包含 .h 的 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;
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 中共享一个外部对象时,如果没有崩溃,我就不走运了。
记录器文档。
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");
很难告诉您您的问题是什么,因为缺少重要信息。
- 您确定它在检查
Data
是否为空指针时崩溃了吗? - 您是否检查过
this
在崩溃时是否有效? - 你有没有在构造函数上打断点,看看什么时候调用的。
虽然看起来您没有制作这些对象的任何副本,但如果没有适当的支持,最好通过删除复制和移动构造函数和赋值运算符来阻止它。有关详细信息,请参阅 https://en.cppreference.com/w/cpp/language/function#Deleted_functions。
查看问题是否是您在创建 ExampleAppLog
的函数之前调用它的一个明显方法是在构造函数中放置一个断点。从上面的代码中,我们无法确定 class 是只创建一次还是多次(从其他地方创建)。
此外,您确定在创建 my_log2
对象之前没有调用 Draw
或 LookHook
。同样,这种事情用调试器测试是微不足道的,但我们很难用手中的部分代码来判断。事实上,由于上面的程序没有 main
,它不是 MCVE。
如果它真的在创建 ExampleAppLog
对象时崩溃,而不是在创建之前尝试使用它时崩溃,那么上面的大部分代码都是无用的并且注释掉代码(并将其从问题中删除) 如果它仍然崩溃,将极大地帮助人们帮助你。
另一方面,如果它因为您在创建它之前使用 my_log2 而崩溃,则说明缺少重现该问题所需的一些代码。
如果问题与初始化顺序有关,那么单例可能是解决方案。在此处查看已接受的答案:How to implement multithread safe singleton in C++11 without using <mutex>.
不管怎么说,都很难帮到你,因为你的问题不够用心。请记住,如果代码不能轻易复制和粘贴,几乎没有人会花更多的时间来创建项目,因为很明显缺少重要的行或信息,因为根据提供的信息,它几乎不可能崩溃指定行。
事实上,我们假设 main 是一个空函数,并且 my_log2
指针和 ExampleAppLog
结构没有其他全局用法,那么函数 reserve
被调用。
作为奖励,如果您提出好的问题,您会在网站上获得更多积分!