簡體   English   中英

字符串:: substr中無法解釋的out_of_range

[英]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的內通話HttpErrorStringExplode的功能呢? 如果尚未安裝,則應通過調試器運行此程序,以便可以准確看到它引發異常的位置。 或者,您可以添加:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM