字符串不是空终止错误
Posted
技术标签:
【中文标题】字符串不是空终止错误【英文标题】:String is not null terminated error 【发布时间】:2014-11-12 11:02:40 【问题描述】:我有一个字符串不是空终止的错误,虽然我不完全确定为什么。在代码的第二部分中使用 std::string 是我尝试解决此问题的尝试之一,尽管它仍然不起作用。
我的初始代码只是使用缓冲区并将所有内容复制到 client_id[]。比发生的错误。如果错误是正确的,这意味着我有 client_id 或者 theBuffer 没有空终止符。我很确定 client_id 没问题,因为我可以在调试模式下看到它。奇怪的是缓冲区也有一个空终止符。不知道出了什么问题。
char * next_token1 = NULL;
char * theWholeMessage = &(inStream[3]);
theTarget = strtok_s(theWholeMessage, " ",&next_token1);
sendTalkPackets(next_token1, sizeof(next_token1) + 1, id_clientUse, (unsigned int)std::stoi(theTarget));
里面 sendTalkPackets 是。我得到一个字符串不是在最后一行终止的。
void ServerGame::sendTalkPackets(char * buffer, unsigned int buffersize, unsigned int theSender, unsigned int theReceiver)
std::string theMessage(buffer);
theMessage += "0";
const unsigned int packet_size = sizeof(Packet);
char packet_data[packet_size];
Packet packet;
packet.packet_type = TALK;
char client_id[MAX_MESSAGE_SIZE];
char theBuffer[MAX_MESSAGE_SIZE];
strcpy_s(theBuffer, theMessage.c_str());
//Quick hot fix for error "string not null terminated"
const char * test = theMessage.c_str();
sprintf_s(client_id, "User %s whispered: ", Usernames.find(theSender)->second.c_str());
printf("This is it %s ", buffer);
strcat_s(client_id, buffersize , theBuffer);
【问题讨论】:
theMessage += "0";
您是否期望这会添加一个空终止符?如果是这样,它不会。
此外,在这种情况下,不需要对这个 char 数组和指针进行任何操作。您可以完全使用std::string
,并且只有当函数调用const char*
时,您最终才会使用c_str()
成员函数来获取C 风格的字符串。
@PaulMcKenzie 是的,这实际上是我的一次尝试遗留下来的代码。现在我正在尝试使用字符串来操作它。
如果你真的想空终止字符串(无论如何都不需要),你会做theMessage.push_back(0);
【参考方案1】:
我认为问题出在这一行:
sendTalkPackets(next_token1, sizeof(next_token1) + 1, id_clientUse, (unsigned int)std::stoi(theTarget));
sizeof(next_token1)+1 将始终给出 5(在 32 位平台上),因为它返回指针的大小而不是 char 数组的大小。
【讨论】:
【参考方案2】:可能导致此(或其他问题)的一件事:如
buffersize
,你通过sizeof(next_token1) + 1
。 next_token1
是
一个指针,它将具有(通常)4 或 8 的恒定大小。你
几乎可以肯定想要strlen(next_token1) + 1
。 (或者也许没有
+ 1
;像这样传递尺寸的约定通常只包括
'\0'
如果它是一个输出缓冲区。还有其他几个
你使用sizeof
的地方,可能有类似的问题。
但最好重做整个逻辑来使用
std::string
无处不在,而不是所有这些 C 例程。不
担心缓冲区大小和'\0'
终止符。 (对于协议
缓冲区,我还找到了 std::vector<char>
或 std::vector<unsigned char>
很有用。这是在std::string
中的内存之前
保证是连续的,但即使在今天,它似乎也更多地对应
与我正在处理的抽象非常接近。)
【讨论】:
【参考方案3】:你不能只做
std::string theMessage(buffer);
theMessage += "0";
这在两个方面都失败了:
std::string
构造函数不知道 buffer
在哪里结束,如果 buffer
不是 0 终止的。所以theMessage
可能是垃圾并包含随机内容,直到在缓冲区之外的内存中找到某个零字节。
将字符串“0”附加到theMessage
没有帮助。您想要的是在某处放置一个零字节,而不是值 0x30(这是用于显示零的 ascii 代码)。
解决这个问题的正确方法是在缓冲区的开头插入一个文字零字节buffersize
插槽。你不能在buffer
本身中这样做,因为buffer
可能不够大,无法容纳额外的零字节。一种可能是:
char *newbuffer = malloc(buffersize + 1);
strncpy(newbuffer, buffer, buffersize);
newbuffer[buffersize] = 0; // literal zero value
或者你可以构造一个std::string
,随你喜欢。
【讨论】:
以上是关于字符串不是空终止错误的主要内容,如果未能解决你的问题,请参考以下文章