将 byte* 转换为 8 个或更少字节的 std::string 会导致崩溃

Converting byte* to std::string with 8 or less bytes causes a crash

正如标题所说,我的程序在转换一个包含 8 个或更少字节的字节数组并从向量中删除前 4 个字节,然后将其转换为字符串后无法正确输出。适用于其他任何东西。我将每个字节保存在一个向量中,我知道 C++ 不喜欢原始指针,但这是最容易使用的解决方案。

具体来说,std::string tostring() 函数是问题所在。

这是我正在使用的class:

编辑:使用最少的可重现示例进行了更新。出于某种原因,当我在此示例中使用 remove 时,它​​根本不起作用。它在我的代码中工作正常,除非它少于 8 个字节。

#include <Windows.h>
#include <vector>
#include <sstream>
#include <iomanip>
#include <iostream>

class Packet {
    typedef std::vector<byte>::iterator iterator; // for iteration and manipulation of the raw data
    typedef std::vector<byte>::const_iterator const_iterator; // for iteration of the const raw data

public:
    std::vector<byte> data;
    Packet();
    Packet(const byte* pdata, size_t cb) { // initializes the packet with a copy of the given data
        data.resize(cb);
        std::copy(pdata, pdata + cb, data.begin());
    }

    size_t size() const { // retuns the size in bytes of the packet
        return data.size();
    }
    void clear() {
        data.clear();
    }
    void removeAt(int i) {
        delete &(data.begin() + i);
        data.erase(data.begin() + i);
    }

    std::string tostring() const { // formats the packet raw data into a string
        std::stringstream ss;

        // stringstream flags for formatting
        // std::hex = hex number output
        // std::setfill('0') = zero fill number formatting
        // std::uppercase = uppercase hex letters
        ss << std::hex << std::setfill('0') << std::uppercase;

        for (auto& b : data) {
            ss << std::setw(2) << static_cast<WORD>(b) << " ";
            // I have no idea why but the only way to make it
            // format it properly is casting it to a 4-byte int
            // setw(2) truncates it back to a 2-digit hex number
            // setw is not "sticky" so it must be set each time
        }
        return ss.str();
    }
};

int main()
{

    /*unsigned char* test = new unsigned char[7];
    test[0] = 0x01;
    test[1] = 0x02;
    test[2] = 0x03;
    test[3] = 0x04;
    test[4] = 0x05;
    test[5] = 0x06;
    test[6] = 0x07;

    Packet* pPacket = new Packet(test, 7);
    pPacket->removeAt(0);
    pPacket->removeAt(0);
    pPacket->removeAt(0);
    pPacket->removeAt(0);*/

    byte* test2 = new byte[12];
    test2[0] = 0x01;
    test2[1] = 0x02;
    test2[2] = 0x03;
    test2[3] = 0x04;
    test2[4] = 0x05;
    test2[5] = 0x06;
    test2[6] = 0x07;
    test2[7] = 0x08;
    test2[8] = 0x09;
    test2[9] = 0x10;
    test2[10] = 0x11;
    test2[11] = 0x12;

    Packet* pPacket2 = new Packet(test2, 12);
    pPacket2->removeAt(0);
    pPacket2->removeAt(0);
    pPacket2->removeAt(0);
    pPacket2->removeAt(0);

    std::cout << pPacket2->tostring() << std::endl;
    system("pause");
}

我假设 byteunsigned char 的别名,WORDint 的别名,尽管这可能是错误的。

delete &(data.begin() + i);

完全没有意义,删除它可以修复代码。 GCC gives a clear error about this。我建议启动你的编译器警告并仔细阅读它们。

main.cpp: In member function ‘void Packet::removeAt(int)’:
main.cpp:28:31: error: taking address of rvalue [-fpermissive]
   28 |         delete &(data.begin() + i);
      |                 ~~~~~~~~~~~~~~^~~~

完全删除此行会导致代码 运行 产生我认为是您预期的输出:

05 06 07 08 09 10 11 12 

Live demo


请注意,您的构造函数可能正在使用成员初始化列表来更有效地初始化您的 data 成员:

Packet(const byte* pdata, size_t cb)
    : data(pdata, pdata + cb) {

}