令人困惑的memcpy行为,如何停止重叠

时间:2019-02-21 10:08:25

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

我有以下课程:

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);

以下是使用信息后每次记忆后内存中行为的屏幕截图:

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

enter image description here enter image description here enter image description here

如您所见,随着程序的执行,第三个memcpy重叠了内存中的名称,关于可能是什么原因的任何线索?我听说过一些有关字符指针和4个字节的信息,这也许就是为什么bridgex1在4个字节之后被切断的原因,但是我不确定如何解决这个问题。

1 个答案:

答案 0 :(得分:2)

如果您有

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

id,名称和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个字符(加上空终止符)。