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

发布于 2024-11-05 08:23:54 字数 1002 浏览 0 评论 0原文

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

由于我是一名 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼中杀气 2024-11-12 08:23:54

我不明白在字节数高于数组目标长度的情况下如何表现
这与数据类型有关吗?

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

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

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

在 C++ 中,在某些情况下也会发生这种情况。但在许多其他情况下,根本没有检测到错误,并且发生的情况是未定义。应用程序可能崩溃,或者可能继续在损坏的状态下运行。它可能会成为一个安全漏洞,或者它可能(理论上)让恶魔从你的鼻子里飞出来。语言规范只是简单地说明了应该发生什么。没有

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

未定义的行为是不好的。不惜一切代价避免。

I do not undestand how does behave this with higher number of bytes than arrays destination length
Is that about data types ?

First, memcpy operates on bytes, not array elements. So if you want to copy an array int[10], for example, you tell memcpy 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 to memcpy 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.

楠木可依 2024-11-12 08:23:54

memcpy 长度参数以字节为单位,而不是数组元素。

代码最好写成:

memcpy((void*)ctx->P, this->BF_PTransformed, 18 * sizeof(unsigned long));
memcpy((void*)ctx->S, (void*)this->sdata, 0x100 * 4 * sizeof(unsigned long));

The memcpy length parameter is in bytes not array elements.

The code would be better written as:

memcpy((void*)ctx->P, this->BF_PTransformed, 18 * sizeof(unsigned long));
memcpy((void*)ctx->S, (void*)this->sdata, 0x100 * 4 * sizeof(unsigned long));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文