【问题标题】:Confusing memcpy behaviour, how to stop overlapping令人困惑的 memcpy 行为,如何停止重叠
【发布时间】:2019-07-15 04:59:52
【问题描述】:

我有以下课程:

BridgingPacketHeader header;
uint32_t ownedByReceiver;
uint32_t nameLength;
uint32_t idLength;
uint32_t uriLength;
char* id;
char* name;
char* uri;

BridgingPacketHeader 是一个包含 5 个 uint32_t 值的类,因此它的大小为 20 个字节。 我正在尝试使用 memcpy 正确填写长度信息并将一些信息复制到 id、name 和 uri 中,但是在调试时,行为很奇怪。名称和 uri 值重叠。

代码:

                //SubCcuPacket *subCcuPk = nullptr;
            uint32_t packet_size = (uint32_t) sizeof(SubCcuPacket);
            //Ensuring the total packet size is correct
            uint32_t idLength = (uint32_t)(std::strlen(subCcu1.second.id) + 1);
            packet_size += idLength;
            uint32_t uriLength = (uint32_t)(std::strlen(subCcu1.second.uri) + 1);
            packet_size += uriLength;
            uint32_t nameLength = (uint32_t)(std::strlen(subCcu1.second.name) + 1);
            packet_size += nameLength;

            SubCcuPacket * subCcuPk = (SubCcuPacket*)malloc(packet_size);
            if (sentUri == subCcu1.second.uri) {
                subCcuPk->ownedByReceiver = 1; //if equal uri
            }
            else {
                subCcuPk->ownedByReceiver = 0; //if sub ccu is not same as reciever
            }       
            
            subCcuPk->idLength = idLength;
            memcpy(&subCcuPk->id, subCcu1.second.id, idLength);

            subCcuPk->nameLength = nameLength;
            memcpy(&subCcuPk->name, subCcu1.second.name, nameLength);

            subCcuPk->uriLength = uriLength;
            memcpy(&subCcuPk->uri, subCcu1.second.uri, uriLength);

            s->send_packet((uint8_t *)subCcuPk, packet_size);

下面是每个memcpy之后在内存中的行为截图,使用信息:

subCcu1.second.uri = 10.92.84.162
subCcu1.second.name = bridgex1
subCcu1.second.id = 1

如您所见,随着程序的运行,第三个 memcpy 与内存中的名称重叠,有什么线索可以解释是什么原因造成的吗?我听说过一些关于字符指针和 4 个字节的事情,这可能就是为什么 bridgex1 在 4 个字节后被切断,但我不确定如何解决这个问题。

【问题讨论】:

  • id、name 和 uri 是指向内存的指针。您正在复制到您的指针,它可能是 4 或 8 字节(取决于 32 位或 64 位编译)。请阅读一般的指针。
  • 你为什么不使用std::string 而不是原始指针?
  • 您应该做的是根据需要为指针分配内存(因此 .name = new char[length]),然后将 memcpy 分配给 .name,而不是 &.name。或者您可以将其更改为 char name[20],然后可以在那里 memcpy 最多 20 个字符。
  • 要通过一个包发送数据,这个包是从要发送的结构中格式化的:: s->send_packet((uint8_t *)subCcuPk, packet_size);
  • 您真的是用 C++ 还是 C 编码?在我看来像 C。

标签: c++ visual-studio pointers char memcpy


【解决方案1】:

如果你有一个像

这样的结构
struct packet {
    BridgingPacketHeader header;
    uint32_t ownedByReceiver;
    uint32_t nameLength;
    uint32_t idLength;
    uint32_t uriLength;
    char* id;
    char* name;
    char* uri;
};

id、name 和 uri 是指向缓冲区内存的指针。如果你想序列化它,你基本上必须手动将它们添加在一起,并跟踪你的内存块的大小。

这样做会更容易

struct packet {
    BridgingPacketHeader header;
    uint32_t ownedByReceiver;
    uint32_t nameLength;
    uint32_t idLength;
    uint32_t uriLength;
    char id[20];
    char name[20];
    char uri[20];
};

因为 sizeof 确实有效,每个参数最多可以容纳 19 个字符(加上空终止符)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 2014-10-11
    相关资源
    最近更新 更多