将 char[] 转换为 Qstring 添加额外的 3 个字符

Convert char[] to Qstring adding extra 3 chars

TL;DR 见底部

背景信息:(透视)

我正在实现一个client-server,客户端请求数据,通过设置的字符缓冲区发送,设置大小为字符[256]

服务器以 2 阶段响应实物响应, 首先使用 header 缓冲区发送 'header packet'(在客户端和服务器上,大小为 char[20]),其中包含要跟随的数据包数量和要发送的最大数据包的大小(分配"data" 缓冲区),

assume the text sent from server is as follows

QString text = QString("TOKEN=1SOMETOKENSTRING123;");
//length of text = 26 char

此 "header packet" 已成功接收、解析和实现,在转换为 QString 时没有任何缺陷,方法是:

//header
char header_buffer[20];
bzero(header_buffer, sizeof (header_buffer));
//assign header_buffer using socket.recv()
QString header = QString(header_buffer);

成功完成

问题信息:

header 被解析并输出属性大小(最大数据包大小)和计数('data' 数据包的数量)

这里是问题所在:

//data packet section

//returns the size of largest packet using the received "header packet" - done successfully
int maxSize = getMaxPacketSize(header_buffer);
//maxSize = 27 char, which is the length of the 'text' String sent from the server, thus

char data_buffer[maxSize]; //char[27]
bzero(data_buffer, sizeof (data_buffer));
//assign data_buffer using socket.recv()
QString data = QString(data_buffer);
qDebug() << data_buffer;   CORRECT  //displays "TOKEN=1SOMETOKENSTRING123;"
qDebug() << data;          ERROR    //displays "TOKEN=1SOMETOKENSTRING123;UUU" 

确切问题:

从 char[] 创建新的 QString 添加 3 'U' 个字符到字符串的末尾:

基本示例:

char cArray[27] //assume it has contents to fill all, size/count = 27
QString str = QString(cArray);
int len = str.length();
//len = 30, last 3 char of str = "UUU"

数据示例(**实际数据):

    int packetSize = getMaxPacketSize(buffer); buffer[20] = "COUNT=2;SIZE=27;[=14=]0[=14=]0[=14=]0[=14=]0"
    char packet[packetSize]; // = 27
    size_t size = sizeof (packet); // = 27 
    bzero(packet, sizeof (packet));

    if (recv(sockfd,packet,sizeof (packet),0) < 0) {
        qDebug() << "ERROR netman: reading data from socket";
        //more code here
    }

    //Add packet to packet_data list

    //NOTE : QList<QString> packet_data = QList<QString>();
    //NOTE: packet[27] = "TOKEN=a7nCrDbaycWx2JzMir4m;"

    packet_data.insert(packetSize-packetNum,QString(packet)); 
    QString d = packet_data.first(); d = "TOKEN=a7nCrDbaycWx2JzMir4m;UUU"

为冗长起见,调试器数据

Locals      
    d   "TOKEN=a7nCrDbaycWx2JzMir4m;UUU"    QString
        [0] 'T'     84  0x0054  QChar
        [1] 'O'     79  0x004f  QChar
        [2] 'K'     75  0x004b  QChar
        [3] 'E'     69  0x0045  QChar
        [4] 'N'     78  0x004e  QChar
        [5] '='     61  0x003d  QChar
        [6] 'a'     97  0x0061  QChar
        [7] '7'     55  0x0037  QChar
        [8] 'n'     110 0x006e  QChar
        [9] 'C'     67  0x0043  QChar
        [10]    'r'     114 0x0072  QChar
        [11]    'D'     68  0x0044  QChar
        [12]    'b'     98  0x0062  QChar
        [13]    'a'     97  0x0061  QChar
        [14]    'y'     121 0x0079  QChar
        [15]    'c'     99  0x0063  QChar
        [16]    'W'     87  0x0057  QChar
        [17]    'x'     120 0x0078  QChar
        [18]    '2'     50  0x0032  QChar
        [19]    'J'     74  0x004a  QChar
        [20]    'z'     122 0x007a  QChar
        [21]    'M'     77  0x004d  QChar
        [22]    'i'     105 0x0069  QChar
        [23]    'r'     114 0x0072  QChar
        [24]    '4'     52  0x0034  QChar
        [25]    'm'     109 0x006d  QChar
        [26]    ';'     59  0x003b  QChar
        [27]    'U'     85  0x0055  QChar
        [28]    'U'     85  0x0055  QChar
        [29]    'U'     85  0x0055  QChar
    message "AUTH;U=user@example;P=Pass;"   char *
    packet  "TOKEN=a7nCrDbaycWx2JzMir4m;"   char [27]
    packetNum   1   int
    packetSize  27  int
    s   "COUNT=2;SIZE=27;"  QString
    size    27  size_t
    this    @0x7fffffffd190 netman
        buffer  "COUNT=2;SIZE=27;[=15=]0[=15=]0[=15=]0[=15=]0"  char [20]
        cli_addr    @0x7fffffffd1c0 sockaddr_in
        clilen  1431695692  socklen_t
        n   1436538608  int
        newsockfd   32767   int
        packet_data <1 items>   QList<QString>
        serv_addr   @0x7fffffffd1b0 sockaddr_in
        server  @0x7ffff5f071c0 hostent
        sockfd  13  int

我不知道这 3 个额外的字符是从哪里来的!

有人suggestions/ideas吗?

这里的主要问题是您将 char* 传递给需要 C 字符串的函数。即,末尾为零值的字符串。但是您从套接字输入的内容不包含这样一个字节。

读取数组末尾是未定义的行为,但在这种情况下很容易推断会发生什么:读取字节直到找不到空值,并且很快就会找到它(在 3 个字节之后)1.

您可以通过使用函数来轻松修复它,这些函数获取它们应该从数组中读取的确切字节数。

最简单的方法是使用QString的成员函数fromUtf8 or fromLatin1 or fromLocal8Bit提供你要读取的字节数:

QString str = QString::fromUtf8(cArray, number_of_bytes);

也就是说,考虑使用 QByteArray 从网络读取数据:

QByteArray data(cArray, number_of_bytes);

1 关于未定义行为所发生的事情的推理应该持保留态度,因为如果编译器能够探测到它发生的话,几乎可以自由地做任何事情。

您使用什么编译器(版本和 cppflags)?

//returns the size of largest packet using the received "header packet" - done successfully
int maxSize = getMaxPacketSize(header_buffer);
//maxSize = 27 char, etc

char data_buffer[maxSize]; //char[27]
//               ^
// really?-------+ Variable Length Array on standard C++?
// does this even compile?

VLA on SO.

cppreference.com 上的数组声明:

noptr-declarator [ expr(optional) ] attr(optional)

...

  • expr - an integral constant expression (until C++14) a converted constant expression of type std::size_t (since C++14), which evaluates to a value greater than zero

上面的相关性如何:如果代码编译(假设有警告而不是错误),这可能会导致未定义的行为 - 例如随后的函数调用(例如 QString 构造函数)覆盖了 VLA 的一部分(在堆栈上),在这种情况下消除了 nul 终止字符,在其他情况下可能会产生其他影响。
如果发生这种情况,检查(在调试时)缓冲区的内容(在最后一个示例中,packet var 而不是 d var)应该会发现更改。