将 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");
}
我假设 byte
是 unsigned char
的别名,WORD
是 int
的别名,尽管这可能是错误的。
行
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
请注意,您的构造函数可能正在使用成员初始化列表来更有效地初始化您的 data
成员:
Packet(const byte* pdata, size_t cb)
: data(pdata, pdata + cb) {
}
正如标题所说,我的程序在转换一个包含 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");
}
我假设 byte
是 unsigned char
的别名,WORD
是 int
的别名,尽管这可能是错误的。
行
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
请注意,您的构造函数可能正在使用成员初始化列表来更有效地初始化您的 data
成员:
Packet(const byte* pdata, size_t cb)
: data(pdata, pdata + cb) {
}