This is a bug analysis record encountered when using QByteArray
scene
- When programming with QTcpSocket, a custom structure is used for data communication. The structure is as follows, where char* load is the address of the message body. In actual use, after using readALL to read the data stream, subpackage and group the package. When using the char* QByteArray::data interface to assign a value to load, the program will crash.
typedef struct
{
unsigned int send_id; // 发送方的ID(网络的IP、SRIO的ID)
unsigned int recv_id; // 接收方的ID(网络的IP、SRIO的ID)
unsigned int msg_type : 8; // 消息类型
unsigned int len : 24; // 消息长度,字节数
unsigned int conn_type: 8; // 连接类型,TCP、UDP等
unsigned int pkg_num : 8; // 总的包数(用于组包传输)
unsigned int pkg_idx : 8; // 子包索引(用于组包传输),从1计数
unsigned int rsvd : 8; // 保留位
unsigned int check_sum; // 校验位
char* load; // 消息体地址
} DispCtrlMsg;
test program
Obviously it is the assignment of a char* pointer, but the program crashes; directly defining a char* pointer for assignment fails.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const int headLength = sizeof(DispCtrlMsg) - sizeof(char*);
QByteArray str;
str.resize(26);
for(int i=0;i<str.size();i++){
str[i]='a';
}
DispCtrlMsg *msg = new DispCtrlMsg();
msg = (DispCtrlMsg*)str.left(headLength).data();
int len = str.size();
QByteArray r = str.right(len - headLength);
cout << r.data() << endl;
cout <<"1) "<< hex<<&msg->load <<endl;
// msg->load = new char[1]; //注释这一行即崩溃。
cout <<"2) "<< hex<<&msg->load <<endl;
msg->load = r.data();
cout <<"3) "<< hex<<&msg->load << endl;
cout <<"4) "<< hex<<msg->load << endl;
cout <<"5) "<< sizeof(msg->load) <<endl;
char *c = r.data();
cout <<"direct char* "<< c <<endl;
delete msg->load;
return a.exec();
}
- The test result is shown in the figure, comment out, after new char[1], the program will crash. The length of new char[] only needs to be greater than or equal to 1.
Temporary solution
- When using the pointer assignment in the structure, use new or malloc to copy the content instead of using pointer assignment to point to the source.
msg->load is just a pointer, it can point to a character or a string. However, this method will lead to resource leakage. Because the new char is not used, and because msg->load no longer points to the space of this character, there is no chance that it will be released again, so this 1-bit space is a resource leak.
Reason for adding:
In the forced type conversion,
the length of QByteArray r = str.right(len-headLength); r is less than the length of the structure. Therefore, the char* load in the structure does not allocate space. Therefore, the program illegally accesses the memory. collapse.
Solutions
Create a structure object, or use malloc to allocate space for the structure pointer. The method of copying is adopted when reading data.