![](/img/trans.png)
[英]'std::out_of_range' what(): basic_string::substr: __pos
[英]Unexplained out_of_range in string::substr
調用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);
這引發了同樣的錯誤。 現在,我知道這是完全有效和正確的代碼,但是仍然會引發錯誤。 //刪除了源鏈接
我對樣本進行了一些修改,以減少使用的壓痕量。
有5個“測試用例”,沒有一個會引起任何問題。 您能否提供示例請求以重現您遇到的問題。
編輯:忘記提及:如果此示例原樣(帶有注釋掉的位)不產生該錯誤,則最好的選擇是您在StringExplode
函數中有一個錯誤。 您可以發布其來源,以獲得更有用的建議。
EDIT2:在您的StringExplode
,更改results[tmpKey] = tmpKey.substr(found+1);
results[tmpKey] = tmpResult[i].substr(found+1);
。 將size_t found
int found
更改為size_t found
,並刪除所有if (found > 0)
,這將解決您神秘的out_of_range。 你substr
-ing一個錯誤的字符串。 以防萬一,下面的代碼已修復:
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;
}
可以預期地輸出:
[做事]
[做事]
[做事]
[]
[]
你確定它的失敗對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
確實引發了異常,那么您將知道,因為該程序將打印“ calling substr”而沒有匹配的“ finishing call substr”。 但是,如果打印出調試消息對,或者根本不打印,則其他情況將引發異常。
您的代碼有一件很明顯的錯誤:
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()錯誤。
看起來您之后需要其他
if(bodypos==std::string::npos)
{
HttpError(...);
}
否則,您使用bodypos = npos調用substr
您可能會考慮使用(無符號)類型std::string::size_type
而不是int
。
您為什么在這里將find的結果強制轉換為int: int(request.find("register"))!=std::string::npos
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.