为了修复旧程序而进行反编译会很痛苦.
因为我是C#开发人员,所以我不明白有些奇怪的事情.我需要一个C++技巧专家来帮助我理解"memcpy()"的行为.
这是我玩的:
unsigned char sdata[] = { 0x54,
... many values (=4100) ...,
0x00 };
Run Code Online (Sandbox Code Playgroud)
然后
unsigned char BF_PTransformed[4*18] = { 0xC6,
... many values (=72) ...,
0x7B };
Run Code Online (Sandbox Code Playgroud)
和
struct BLOWFISH_CTX
{
unsigned long P[16 + 2];
unsigned long S[4][256];
};
Run Code Online (Sandbox Code Playgroud)
这是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);
}
Run Code Online (Sandbox Code Playgroud)
我不明白这是如何使用更高的字节数而不是数组目标长度.那是关于数据类型的吗?
有人可以解释它,以便C#开发人员可以理解吗?
(甚至不要提到Blowfish这个词.这个"特殊"实施的2天让我生病了)
小智 5
memcpy length参数以字节为单位,而不是数组元素.
代码可以更好地编写为:
memcpy((void*)ctx->P, this->BF_PTransformed, 18 * sizeof(unsigned long));
memcpy((void*)ctx->S, (void*)this->sdata, 0x100 * 4 * sizeof(unsigned long));
Run Code Online (Sandbox Code Playgroud)
我不知道如何使用比数组目标长度更高的字节数来表现这一点是关于数据类型的吗?
首先,memcpy操作字节,而不是数组元素.因此int[10],例如,如果要复制数组,则告诉memcpy复制40个字节(10*sizeof(int)).因此传递给memcpy的参数(本例中为40)可能大于数组元素(10)的数量,因为每个数组元素占用多个字节.
其次,如果你真的告诉memcpy复制过去数组的末尾(比方说,如果我们memcpy在上面的例子中传递了43作为参数),那么你会有未定义的行为.
在C和C++中,在编译时或运行时不需要检测许多错误条件.在C#中,如果您在运行时尝试了非法操作,则会抛出异常.
在C++中,在某些情况下也会发生这种情况.但在许多其他情况下,根本检测不到错误,所发生的情况是未定义的.应用程序可能会崩溃,或者可能继续以损坏的状态运行.它可能会成为一个安全漏洞,或者它(理论上)可能使恶魔飞出你的鼻子.语言规范根本没有说明应该发生什么.
读取数组的末尾(就像你告诉memcpy复制超过数组的长度一样)是一个这样的场合.如果您尝试这样做,您的应用程序有一个错误,但没有说它在您尝试运行它时会如何表现.如果你很幸运,它会崩溃.在最坏的情况下,它会继续运行,因为那将是不一致的状态,它可能会崩溃后(使得错误更难诊断),或者它可能,而不是崩溃,只是产生错误的结果,或者当您在计算机上运行它时,它似乎可以正常工作,但当您的客户运行您的应用程序时,它会表现出任何这些行为.
未定义的行为很糟糕.不惜一切代价避免.