string :: substr中的原因不明的out_of_range

sta*_*tan 1 c++ g++

调用substr时,我得到了一个关于std :: out_of_range的非常烦人的错误.确切的错误是

抛出'std :: out_of_range'的实例后调用terminate
():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);
Run Code Online (Sandbox Code Playgroud)

在另一个:

 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";
    }

   }
Run Code Online (Sandbox Code Playgroud)

更新:

std::string request2("P\r\nregister\r\nusername=hello\r\n\r\n");

std::string body = request2.substr(4);
Run Code Online (Sandbox Code Playgroud)

这引发了同样的错误.现在我知道这是完全有效和正确的代码,但它仍然抛出错误.//删除了源链接

Dmi*_*try 6

我稍微修改了你的样本以减少使用的缩进量.
有5个"测试用例",没有任何问题.您能否提供样本请求来重现您遇到的问题.

编辑:忘记提及:如果这样的样本(带有注释掉的位)不会产生错误,那么最好的办法是你的StringExplode函数中有一个错误.您可以发布其来源,以获得更有用的建议.

编辑2:在你的StringExplode,results[tmpKey] = tmpKey.substr(found+1);改为results[tmpKey] = tmpResult[i].substr(found+1);.更改int foundsize_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());
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

初始测试代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

这预示着:

[做事]
[做事]
[做事]
[]
[]

  • @Stanislav Palatnik,在答案中检查我的EDIT2,这应该有所帮助. (2认同)