gpt4 book ai didi

c++ - CRTP 的这个用例是否被视为未定义的行为?

转载 作者:行者123 更新时间:2023-11-30 04:01:11 26 4
gpt4 key购买 nike

我正在尝试在固定大小的缓冲区中构建一条消息,我的图书馆的用户会在其中提供一些数据。我曾经通过给用户一个指向缓冲区的指针并让他们写入它,并通过引用他们写入的字节数来设置一个 size_t 参数来做到这一点。我想放弃这种方法,因为它允许用户意外损坏缓冲区,或者错误地报告写入的字节数。为此,我做了以下工作:

定义了这个结构:

template <class Derived>
struct MsgBase
{
size_t size() const { return sizeof(Derived); }
const char* data() const {
const Derived* dat = static_cast<const Derived*>(this);
return reinterpret_cast<const char*>(dat);
}
};

而且我要求,如果用户想要发送某些数据,他们需要定义一个继承自此的结构,其中包含要发送的数据。例如:

struct Example : MsgBase<Example>
{
int a;
double b;
char c[7];
};

我定义了这个类来帮助他们将数据传送到我的图书馆:

class Loader
{
public:
Loader() : size(0), data(0) {}

size_t size() const { return size; }
const char* data() const { return data; }

template<class T> void loadData(const T& t) {
size = t.size();
data = t.data();
}

private:
size_t size;
const char* data;
};

所以我这样调用它们:

{
//pos is a char* to a point in a buffer of data
Loader loader;
onLibraryCall(&loader);
memcpy(pos, loader.data(), loader.size());
}

用户正在这样做:

void onLibraryCall(Loader* loader)
{
Example e;
e.a = 3;
e.b = 2.7;
e.c[0] = //bla fill out some stuff here

loader->loadData(e);
}

这在我使用不同版本的 gcc 编译测试过的无数二进制文件中都有效,但在一个特定的二进制文件中一致地破坏了上述消息。 gdb 和 valgrind 根本没有帮助我,如果我尝试记录上面调用周围发生的事情,问题就会消失。这让我觉得其中存在未定义的行为,但我不完全确定它可能在哪里或者我可以做些什么来进一步调试它?

我检查以确保任何此类定义的结构都是 POD。我也知道所有的结构是什么,目前它们都是整数类型和固定大小的小数组的组合。

最佳答案

Loader::loadData() 中,您通过 MsgBase::data() 存储参数的 this 指针的拷贝。

onLibraryCall() 中,您在堆栈上分配一个 Example 实例,然后将对它的引用传递给 Loader::loadData()Example 实例在此函数结束时超出范围并被销毁。

在调用代码中,onLibraryCall() 返回后,memcpy() 调用从缓存在 Loader::loadData() 中的指针中读取,但该指针现在指向一个不再使用的内存地址,因此您有未定义的行为。

关于c++ - CRTP 的这个用例是否被视为未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25917117/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com