为了修复旧程序而进行反编译可能会很痛苦。
作为一名 C# 开发人员,有些奇怪的事情我不明白。 我需要 C++ 技巧专家来帮助我理解“memcpy()”的行为。
这是我玩的东西:
unsigned char sdata[] = { 0x54,
... many values (=4100) ...,
0x00 };
然后
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 天让我恶心啊哈)
最佳答案
I do not undestand how does behave this with higher number of bytes than arrays destination length Is that about data types ?
首先,memcpy
对字节而不是数组元素进行操作。所以如果你想复制一个数组 int[10]
,例如,你告诉 memcpy
复制 40 个字节 (10*sizeof(int)
).因此传递给 memcpy 的参数(在本例中为 40)可以大于数组元素的数量(10),因为每个数组元素占用超过一个字节。
其次,如果你真的告诉 memcpy
复制数组的末尾(比如,如果我们在上面的例子中将 43 作为参数传递给 memcpy
),那么你就会有未定义的行为。
在 C 和 C++ 中,不需要在编译时或运行时检测到许多错误情况。在 C# 中,如果您在运行时尝试了非法操作,则会抛出异常。
在 C++ 中,某些 情况下也会发生这种情况。但在许多其他情况下,根本没有检测到错误,并且发生的事情是未定义。应用程序可能 崩溃,或者它可能继续在损坏的状态下运行。它可能成为一个安全漏洞,或者它可能(理论上)让恶魔从你的 Nose 里飞出来。语言规范只是没有说明应该发生什么。
读取超过数组的末尾(如果您告诉 memcpy
复制超过数组的长度,您就会这样做)就是这样一种情况。如果您尝试这样做,您的应用程序就会有错误,但并没有说明当您尝试运行它时它将如何表现。如果您幸运,它会崩溃。在最坏的情况下,它会继续运行,因为那时它会处于不一致的状态,稍后它可能会崩溃(使错误更难诊断),或者它可能,而不是崩溃,只是产生错误的结果,或者当您在您的计算机上运行它时它可能看起来工作正常,但当您的客户运行您的应用程序时表现出任何这些行为。
未定义的行为是不好的。不惜一切代价避免。
关于C++ memcpy() 棘手的使用,需要行为理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5921851/