Este es un registro de análisis de errores encontrado al usar QByteArray
escena
- Cuando se programa con QTcpSocket, se utiliza una estructura autodefinida para la comunicación de datos, la estructura es la siguiente, donde char * load es la dirección del cuerpo del mensaje. En uso real, después de usar readALL para leer el flujo de datos, subpaquete y agrupe el paquete. Cuando se usa la interfaz char * QByteArray :: data para asignar un valor a cargar, el programa se bloqueará.
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;
Programa de prueba
Obviamente, es la asignación de un puntero char *, pero el programa falló; la definición directa de un puntero char * para la asignación falló.
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();
}
- El resultado de la prueba se muestra en la figura, comentar, después de un nuevo carácter [1], el programa se bloqueará. La longitud del nuevo carácter [] solo debe ser mayor o igual a 1.
Solución temporal
- Cuando use la asignación de puntero en la estructura, use new o malloc para copiar el contenido en lugar de usar la asignación de puntero para apuntar a la fuente.
msg-> load es solo un puntero, puede apuntar a un carácter o una cadena. Sin embargo, este método provocará una fuga de recursos. Debido a que el nuevo carácter no se usa y debido a que msg-> load ya no apunta al espacio de este carácter, no hay posibilidad de que se libere nuevamente, por lo que este espacio de 1 bit es una pérdida de recursos.
Razón para agregar:
En la conversión de tipo forzada,
la longitud de QByteArray r = str.right (len-headLength); r es menor que la longitud de la estructura. Por lo tanto, la carga char * en la estructura no asigna espacio. Por lo tanto, el programa accede ilegalmente a la memoria. colapso.
Soluciones
Cree un objeto de estructura o utilice malloc para asignar espacio para el puntero de estructura. El método de copia se adopta al leer datos.