【问题标题】:deserializing pointer from struct gives pointer to pointer?从结构反序列化指针给出指向指针的指针?
【发布时间】:2022-01-10 08:05:27
【问题描述】:

给定以下结构:

// sizeof == 8
struct Data {
    int Foo;
    int Bar;
};

// sizeof == 16
struct __declspec(align(8)) Consumer {
    char Padder00[4];
    char Padder01[4];
    
    Data* Data;
};

我希望 Data* 等于一个数字,跨越 8 个字节(就像我在 x64 上一样),这是 Data 类型结构的起始地址。

现在,调试以下示例:

int main()
{
    Consumer consumer;
    consumer.Data = (Data*)malloc(sizeof(Data));
    // consumer.Data    == 0x0000013c86eb1300
    // &consumer.Data   == 0x00000037cdcff660

    consumer.Data->Bar = 1337;
    consumer.Data->Foo = 42069;
    
    char* stepper = (char*)(&consumer);
    stepper += 4;           // skipping 1st padder
    stepper += 4;           // skipping 2nd padder
    
    Data* restored = ((Data*)stepper);
    // restored         == 0x00000037cdcff660
    //                  == &consumer.Data

    free(consumer.Data);
    std::getchar();
    return 0;
}

所以restored == &consumer.Data 而我本来希望它是restored == consumer.Data,更进一步并查看stepper 的每个字节会产生以下结果:

stepper[0] = 0x00
stepper[1] = 0x13
stepper[2] = 0xeb
stepper[3] = 0x86
stepper[4] = 0x3c
stepper[5] = 0x01
stepper[6] = 0x00
stepper[7] = 0x00

// 0x0000013c86eb1300 (little endian)
// 0x0000013c86eb1300 == consumer.Data

总结:

((Data*)stepper) == &consumer.Data == (*(Data**)stepper)

我希望它在哪里

((Data*)stepper) == consumer.Data

那么……这里到底发生了什么巫术?

【问题讨论】:

  • 你为什么期待别的? stepper 首先指向 Consumer 对象的开头,然后通过添加整数逐步遍历该对象。最后你仍然指向Consumer 对象,别无他处。使用转换 (Data*)stepper 的结果会导致未定义的行为,因为在 stepper 指向的位置没有 Data 对象。那里只有一个Data*
  • 您的预期不正确。 stepper 是指针consumer.Data地址,而不是它的值。所以你看到的是((Data*)stepper) == &consumer.Data
  • 做同样的事情,但使用int 而不是Data* - 您是否期望(int) stepperint? (指针没有什么特别之处。)
  • @molbdnilo 谢谢!这很清楚。我想我只是想多了。

标签: c++ pointers memory


【解决方案1】:

错误是这一行

Data* restored = ((Data*)stepper);

应该是

Data* restored = *((Data**)stepper);

stepper 指向Data(字段)所在的位置,它本身就是一个指针。所以取消引用stepper 会给你Data 指针,你需要取消引用它才能得到Data

【讨论】:

  • 使用更明确的Data **address_of_restored = (Data **)stepper; Data *restored = *address_of_restored; 可能更容易理解
猜你喜欢
  • 2018-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-21
  • 2012-03-28
  • 2021-07-14
  • 2013-02-15
相关资源
最近更新 更多