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

标签 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 天让我恶心啊哈)

最佳答案

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/

相关文章:

c++ - 显示列表的并行处理

c++ - 编译时优化 - 从发布二进制文件中删除调试打印

c - 按位运算位检查

c - 如何在 C 函数中使用 realloc

c - 使用 memcpy 的列表中的段错误

C++ memcpy 和愉快的访问冲突

c++ - 为什么 std::ranges::view_interface 使用 CRTP

c++ - 一些应用程序是如何用多种编程语言制作的?

c - 带有结构体数组的 Malloc

c++ - Memcpy 实现,严格别名