在调用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);也会引发同样的错误。现在我知道这是完全有效和正确的代码,但它仍然抛出错误。//删除源链接
发布于 2010-02-13 21:36:39
我稍微修改了你的样本,以减少使用的压痕量。
有5个“测试用例”,没有引起任何问题。请您提供一个示例请求,以重现您所遇到的问题。
编辑:忘了提到:如果这个示例(带有注释位)不会产生错误,那么最好的选择是您的StringExplode函数中有一个bug。你可以发布它的来源,以获得一个更有帮助的建议。
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-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;
}这一产出不出所料:
在做什么
做东西
[]
发布于 2010-02-13 21:24:39
您确定它在该substr上失败了,而不是在HttpError或StringExplode函数中的substr调用上失败了吗?如果您还没有这样做,您应该通过调试器来运行它,这样您就可以准确地看到它抛出异常的位置。或者,您也可以添加一个:
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真的抛出了异常,那么您就会知道,因为程序将打印“调用substr”,而没有匹配的“已完成调用substr”。但是,如果它打印了一对调试消息,或者根本没有输出,那么其他东西就会抛出异常。
发布于 2010-02-13 22:04:29
您的代码有一个相当明显的错误:
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()错误。
https://stackoverflow.com/questions/2258900
复制相似问题