调用substr时,我遇到了一个关于std :: out_of_range的非常烦人的错误。确切的错误是
投掷后终止调用 'std :: out_of_range'的实例 what():basic_string :: substr
我绝对相信tmp_request的长度大于1.无论我传递给substr-1,2还是bodypos,它总会抛出该错误。我在Unix上使用g ++。
我可以包含的唯一有趣的事情是字符串有多个"\r\n"
,包括一个"\r\n\r\n"
。
在一个cpp文件中:
std::string tmp_request, outRequest;
tmp_request = SS_Twitter->readData();
outRequest = SS_Twitter->parse(tmp_request);
在另一个:
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0]=='P')
{
if(request.find("register")!=std::string::npos)
{ //we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
}
else
{
std::string body = request.substr(bodypos);
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
}
}
更新:
std::string request2("P\r\nregister\r\nusername=hello\r\n\r\n");
std::string body = request2.substr(4);
抛出相同的错误。现在我知道这是完全有效和正确的代码,但它仍然抛出错误。 //删除了源链接
答案 0 :(得分:6)
我稍微修改了你的样品以减少使用的压痕量 有5个“测试用例”,没有任何问题。您能否提供一份样本请求来重现您遇到的问题。
编辑:忘记提及:如果这样的样本(带有注释掉的位)不会产生错误,那么最好的办法是你的StringExplode
函数中有一个错误。您可以发布其来源,以获得更有用的建议。
EDIT2:
在StringExplode
中,将results[tmpKey] = tmpKey.substr(found+1);
更改为results[tmpKey] = tmpResult[i].substr(found+1);
。将int found
更改为size_t found
,并移除所有if (found > 0)
,这将修复您神秘的out_of_range。你是substr
- 错误的字符串。以防万一,这是带有修复的代码:
void StringExplode(std::string str, std::string objseparator, std::string keyseperator,
std::map <std::string, std::string> &results)
{
size_t found;
std::vector<std::string> tmpResult;
found = str.find_first_of(objseparator);
while(found != std::string::npos)
{
tmpResult.push_back(str.substr(0,found));
str = str.substr(found+1);
found = str.find_first_of(objseparator);
}
if(str.length() > 0)
{
tmpResult.push_back(str);
}
for(size_t i = 0; i < tmpResult.size(); i++)
{
found = tmpResult[i].find_first_of(keyseperator);
while(found != std::string::npos)
{
std::string tmpKey = tmpResult[i].substr(0, found);
results[tmpKey] = tmpResult[i].substr(found+1);
found = tmpResult[i].find_first_of(keyseperator, found + results[tmpKey].size());
}
}
}
初始测试代码:
#include <iostream>
#include <map>
#include <string>
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0] != 'P')
return outRequest;
if(request.find("register") == std::string::npos)
return outRequest;
//we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
// HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
// you said HttpError returns, so here's a return
return outRequest;
}
std::string body = request.substr(bodypos);
// StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
return outRequest;
}
int main()
{
std::string request("P\r\nregister\r\nusername=hello\r\n\r\n");
std::cout << "[" << parse(request) << "]\n";
request = "Pregisternusername=hello\r\n\r\n";
std::cout << "[" << parse(request) << "]\n";
request = "Pregisternusername=hello";
std::cout << "[" << parse(request) << "]\n";
request = "registernusername=hello";
std::cout << "[" << parse(request) << "]\n";
request = "";
std::cout << "[" << parse(request) << "]\n";
return 0;
}
这可以预见:
[做事]
[做东西]
[做东西]
[]
[]
答案 1 :(得分:1)
您确定substr
上的substr
以及HttpError
或StringExplode
内的std::cout << "calling substr" << std::endl;
来电是否失败?如果还没有,则应该通过调试器运行它,以便您可以准确地看到它抛出异常的位置。或者,您可以添加:
substr
在你致电std::cout << "calling substr" << std::endl;
std::string body = request.substr(bodypos);
std::cout << "finished calling substr" << std::endl;
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
之前的一行,以及之后的类似行,以便它看起来像:
substr
如果{{1}}确实抛出了异常,那么你就会知道,因为程序将打印“calling substr”而没有匹配的“完成的调用substr”。但是,如果它打印出一对调试消息,或者根本没有,那么其他东西就会抛出异常。
答案 2 :(得分:1)
您的代码有一个相当明显的错误:
int k = read(ns, buf, sizeof(buf)-1);
buf[k] = '\0';
您没有检查read()是否成功 - 它在失败时返回-1,如果发生这种情况会导致各种内存损坏问题。
此外:
char * buf2 = const_cast<char *>(reply.c_str());
write(ns,buf2,sizeof(buf2));
你正在使用指针的大小 - 你想要输出字符串的长度:
write(ns, buf2, reply.size() );
你应该再次测试写入成功并且它写了你请求的字节数,尽管这不应该直接导致substr()错误。
答案 3 :(得分:0)
看起来你需要一个
之后的其他人if(bodypos==std::string::npos)
{
HttpError(...);
}
否则你用bodypos = npos
调用substr答案 4 :(得分:0)
您可以考虑使用(无符号)类型std::string::size_type
代替int
。
为什么要将find的结果转换为int:
int(request.find("register"))!=std::string::npos