C++ memcpy() 的使用很棘手,需要理解行为
反编译以修复旧程序可能会很痛苦。
由于我是一名 C# 开发人员,所以有一些奇怪的事情我不明白。 我需要一位 C++ 技巧专家来帮助我理解“memcpy()”的行为。
这是我所玩的:
unsigned char sdata[] = { 0x54,
... many values (=4100) ...,
0x00 };
then
unsigned char BF_PTransformed[4*18] = { 0xC6,
... many values (=72) ...,
0x7B };
和
struct BLOWFISH_CTX
{
unsigned long P[16 + 2];
unsigned long S[4][256];
};
这是 memcpy()
调用:
void BFInit()
{
BLOWFISH_CTX* ctx = &this->BlowfishContext;
memcpy((void*)ctx->P, this->BF_PTransformed, 18*4);
memcpy((void*)ctx->S, (void*)this->sdata, 0x100*4*4);
}
问题
我不明白当字节数高于数组目标长度时,这是如何表现的。 与数据类型有关吗?
有人可以解释一下,以便 C# 开发人员可以理解吗?
(甚至不要试图提及 Blowfish 这个词。这个“特殊”实现的 2 天让我感到恶心啊哈哈)
Decompilation so as to fix an old program can be painful.
As I'm a C# developer, there's something strange I don't understand.
I would need a C++ tricks expert to help me understand the behaviour of "memcpy()".
Here's what I play with:
unsigned char sdata[] = { 0x54,
... many values (=4100) ...,
0x00 };
then
unsigned char BF_PTransformed[4*18] = { 0xC6,
... many values (=72) ...,
0x7B };
and
struct BLOWFISH_CTX
{
unsigned long P[16 + 2];
unsigned long S[4][256];
};
Here are the memcpy()
calls:
void BFInit()
{
BLOWFISH_CTX* ctx = &this->BlowfishContext;
memcpy((void*)ctx->P, this->BF_PTransformed, 18*4);
memcpy((void*)ctx->S, (void*)this->sdata, 0x100*4*4);
}
Questions
I do not understand how this behaves with higher number of bytes than arrays destination length.
Is that about data types?
Can someone explain it so it can be understood by a C# developer?
(And do not even try to mention the word Blowfish. 2 days on this "special" implementation made me sick ahah)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,memcpy 对字节进行操作,而不是对数组元素进行操作。因此,例如,如果您想复制数组
int[10]
,您可以告诉memcpy
复制 40 个字节 (10*sizeof(int))。因此传递给 memcpy 的参数(本例中为 40)可以大于数组元素的数量 (10),因为每个数组元素占用多个字节。
其次,如果您真正告诉memcpy复制到数组末尾(例如,如果我们在上面的示例中将43作为参数传递给memcpy),那么您会有未定义的行为。
在 C 和 C++ 中,许多错误条件不需要在编译时或运行时检测到。在 C# 中,如果您在运行时尝试了非法的操作,就会抛出异常。
在 C++ 中,在某些情况下也会发生这种情况。但在许多其他情况下,根本没有检测到错误,并且发生的情况是未定义。应用程序可能崩溃,或者可能继续在损坏的状态下运行。它可能会成为一个安全漏洞,或者它可能(理论上)让恶魔从你的鼻子里飞出来。语言规范只是简单地说明了应该发生什么。没有。
读取超出数组末尾的内容(就像告诉 memcpy 复制超过数组长度的内容一样)就是这样一种情况。如果您尝试这样做,您的应用程序就会出现错误,但没有说明当您尝试运行它时它会如何表现。如果你幸运,它就会崩溃。在最坏的情况下,它将继续运行,因为那时它将处于不一致的状态,并且它可能稍后崩溃(使错误更难以诊断),或者它可能,而不是崩溃,只是产生错误的结果,或者当您在计算机上运行它时它可能看起来工作正常,但当您的客户运行您的应用程序时却表现出任何这些行为。
未定义的行为是不好的。不惜一切代价避免。
First,
memcpy
operates on bytes, not array elements. So if you want to copy an arrayint[10]
, for example, you tellmemcpy
to copy 40 bytes (10*sizeof(int)
). So the argument passed to memcpy (40 in this example) can be greater than the number of array elements (10), because each array element takes up more than one byte.Second, if you genuinely tell
memcpy
to copy past the end of the array (say, if we passed 43 as the argument tomemcpy
in the above example), then you would have undefined behavior.In C and C++, many error conditions are not required to be detected at compiletime or runtime. In C#, an exception would be thrown if you tried something illegal at runtime.
In C++, that happens in some cases too. But in many others, the error isn't detected at all, and what happens is undefined. The application may crash, or it may continue to running in a corrupted state. It may become a security vulnerability, or it may (in theory) make demons fly out of your nose. The language spec simply says nothing about what should happen.
And reading past the end of an array (as you'd do if you tell
memcpy
to copy more than the length of the array) is one such occasion. If you try to do it, your application has a bug, but there's no saying how it will behave when you try to run it. If you're lucky, it'll crash. In the worst case, it'll continue running, because then it'll be in an inconsistent state, and it might crash later (making the error much harder to diagnose), or it might, instead of crashing, simply produce the wrong results, or it may appear to work correctly when you run it on your computer, but exhibit any of these behaviors when your customer runs your application.Undefined behavior is bad. Avoid at all costs.
memcpy 长度参数以字节为单位,而不是数组元素。
代码最好写成:
The memcpy length parameter is in bytes not array elements.
The code would be better written as: