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

时间:2016-10-22 21:22:58

标签: c++ qt sockets char qstring

参见TL的底部; DR

背景信息(透视)

我正在实现一个客户端服务器,客户端请求数据,通过set char缓冲区发送,设置大小为char [256]

服务器以2阶段响应进行实物响应, 首先发送一个'标头包'使用头缓冲区(在客户端和服务器上都有大小为char [20]),包含要遵循的数据包数量和要发送的最大数据包的大小(以分配"数据"缓冲区),

  

假设从服务器发送的文本如下

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

这个"标头包"通过使用:

成功接收,解析和实现,无需转换为QString
//header
char header_buffer[20];
bzero(header_buffer, sizeof (header_buffer));
//assign header_buffer using socket.recv()
QString header = QString(header_buffer);

这已成功完成

问题信息:

解析标头并输出属性大小(最大数据包大小)和计数('数据'要跟随的数据包的数量)

这就是问题所在:

//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&#39; U&#39;字符串结尾的字符:

基本示例:

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;\000\000\000\000"
    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;\000\000\000\000"  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

我不知道这三个额外的字母来自哪里!

任何建议/想法?

2 个答案:

答案 0 :(得分:2)

这里的主要问题是你将char*传递给期望c字符串的函数。也就是说,最后是一个零值的字符串。但是来自套接字的输入不包含这样的字节。

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

你可以通过使用那些采用从数组中读取的确切字节数的函数来轻松修复它。

最简单的方法是使用QString的{​​{3}}或fromUtf8fromLatin1成员函数来提供您想要读取的字节数:

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

话虽如此,考虑使用fromLocal8Bit从网络读取数据:

QByteArray data(cArray, number_of_bytes);

1 推理未定义行为会发生什么,应该用盐,因为编译器可以自由地做任何事情,如果他们可以探测它发生。

答案 1 :(得分: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 - 一个integral constant expression(直到C ++ 14)转换后的constant expression of type std::size_t(自C ++ 14开始),其值为大于零
  •   

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