C ++ memcpy()棘手的使用,需要行为理解

时间:2011-05-07 15:01:51

标签: c++ c memcpy

反编译以修复旧程序可能会很痛苦。

由于我是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天让我生病了)

2 个答案:

答案 0 :(得分: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));

答案 1 :(得分:5)

  

我并不认为如何使用比数组目标长度更多的字节数来表现这一点   这是关于数据类型吗?

首先,memcpy对字节进行操作,而不是数组元素。因此,例如,如果要复制数组int[10],则告诉memcpy复制40个字节(10*sizeof(int))。因此传递给memcpy的参数(本例中为40)可能大于数组元素(10)的数量,因为每个数组元素占用的字节数不止一个。

其次,如果你真的告诉memcpy复制超过数组的末尾(例如,如果我们在上面的例子中将43作为参数传递给memcpy),那么你将拥有未定义的行为

在C和C ++中,不需要在编译时运行时检测到许多错误条件。在C#中,如果您在运行时尝试了非法操作,则会抛出异常。

在C ++中,这也发生在一些案例中。但在许多其他情况下,根本检测不到错误,发生的情况是 undefined 。应用程序可能崩溃,或者它可能继续在损坏的状态下运行。它可能会成为一个安全漏洞,或者它(理论上)可能使恶魔飞出你的鼻子。语言规范简单地说 nothing 关于应该发生什么。

读取数组的末尾(如果你告诉memcpy复制超过数组的长度就行了)就是这样一个场合。如果您尝试这样做,您的应用程序有一个错误,但没有说它在您尝试运行它时会如何表现。如果你幸运,它会崩溃。在最坏的情况下,它将继续运行,因为它将处于不一致的状态,并且它可能会在以后崩溃(使错误更难以诊断),或者它可能会,而不是崩溃,只是产生错误的结果,或者在您的计算机上运行它时似乎可以正常工作,但在客户运行您的应用程序时会出现任何这些行为。

未定义的行为很糟糕。不惜一切代价避免。