这段代码应该解析请求,提取URI路径,然后提取每个单独的头及其值,然后将所有提取的变量传递给std::vector <const char*> cva
,最终将传递给std::vector<std::vector<const char*>> nv (config.nv.push_back(std::move(cva));)
< / p>
我在这里遇到的问题很少:
print
语句,表明我的解析已经正确完成。 for
循环(在结尾处)具有与预期不同的输出。
#include <vector>
#include <cstring>
#include <iostream>
#include <string>
namespace {
std::vector<std::string> explode(const std::string& str, const char& ch) {
std::string next;
std::vector<std::string> result;
// For each character in the string
for (std::string::const_iterator it = str.begin(); it != str.end(); it++) {
// If we've hit the terminal character
if (*it == ch) {
// If we have some characters accumulated
if (!next.empty()) {
// Add them to the result vector
result.push_back(next);
next.clear();
}
} else {
// Accumulate the next character into the sequence
next += *it;
}
}
if (!next.empty())
result.push_back(next);
return result;
}
}
int main() {
// this is an example of how my reqlines looks like
std::vector<std::string> reqlines;
reqlines.push_back("https://endpoint/test1");
reqlines.push_back("https://endpoint/test2\theader1:1234\tcookie:abcd");
reqlines.push_back("https://endpoint/test3\theader1:5678");
reqlines.push_back("https://endpoint/test4");
reqlines.push_back("https://endpoint/test5");
std::vector<std::string> paths;
std::vector<std::string> extraheaders;
std::vector<std::vector<std::string> > tokenized;
int count = 0; // keeps track of each request number so I can access its corresponding extra headers from extraheaders vector
bool cond = true;
if (cond){
// creating which will be used to store my requests paths as well as extra headers
// This has to be a const char * vector since it will be used by an external library which requires such type
std::vector<const char *> cva;
for (auto &req : reqlines){
unsigned int pos = req.find_first_of("\t", 0);
if (pos == -1){
paths.push_back(req);
extraheaders.push_back(" ");
} else {
paths.push_back(req.substr(0, pos));
extraheaders.push_back(req.substr(pos+1, std::string::npos));
}
}
for (auto &path : paths){
cva.push_back(":path");
cva.push_back(path.c_str()); // adding the URI path into cva variable
// explode function which returns a std::vector<std::string> when passing an std::string to it
tokenized.push_back(explode(extraheaders[count], '\t')); // extracting the vector<std::string> of all extra headers
// if (tokenized[count][0].compare(" ") == 0){
// printf(" %d element is empty is skipped \n");
// }else {
for (auto &tok : tokenized[count]){ // looping through extra headers of request number "count", parsing header name/value and adding it to cva
printf(" %d tok %s\n", __LINE__, tok.c_str());
printf(" %d tok address %d\n", __LINE__, &tok);
unsigned int pos = tok.find_first_of(":", 0);
if (pos == -1 )
printf(" %d there are no headers \n", __LINE__);
else {
printf("header name: %s\n", (tok.substr(0, pos)).c_str());
printf("header value: %s\n", (tok.substr(pos+1, std::string::npos)).c_str());
cva.push_back((tok.substr(0, pos)).c_str());
cva.push_back((tok.substr(pos+1, std::string::npos)).c_str());
}
}
cva.push_back(":version"); // adding version header
cva.push_back("HTTP/1.1"); // adding version header number
cva.push_back(nullptr); // adding nullptr (which is how nv is expecting cva to be terminated)
count++;
// passing the cva content to nv
//config.nv.push_back(std::move(cva));
}
// Below are the printing statement to check the values of the different variables I created and populated
// above, my problem is that the population process puts some values into my variables however printing
// the content of the those variables shows different values from what I am expecting
std::cout << " " << std::endl << std::endl;
std::cout << "Printing cva" << std::endl;
for (auto &elem : cva){
if (elem == nullptr)
std::cout << static_cast<void*>(nullptr) << std::endl;
else
std::cout << &elem << " " <<elem << std::endl;
}
std::cout << " " << std::endl << std::endl;
std::cout << "Printing paths" << std::endl;
for (auto &path : paths){
std::cout << &path << " " << path << std::endl;
}
std::cout << " " << std::endl << std::endl;
std::cout << "Printing headers" << std::endl;
for (auto &hed : extraheaders) {
std::cout << &hed << " "<<hed << std::endl;
}
}
}
预期输出应为:
Printing cva
:path
endpoint:port/test1
:version
HTTP/1.1
0
:path
endpoint:port/test2
:header1
1234
:cookie
abcd
:version
HTTP/1.1
0
:path
endpoint:port/test3
:header1
5678
:version
HTTP/1.1
0
:path
endpoint:port/test4
:version
HTTP/1.1
0
:path
endpoint:port/test5
:version
HTTP/1.1
0
实际输出:
Printing cva
:path
endpoint:port/test1
:version
HTTP/1.1
0
:path
endpoint:port/test2
header1 // for test2 request, header1 value is 1234
5678
header1 // header 1 should not be printed twice
5678
// Missing cookie header and value
:version
HTTP/1.1
0
:path
endpoint:port/test3
header1
5678
:version
HTTP/1.1
0
:path
endpoint:port/test4
:version
HTTP/1.1
0
:path
endpoint:port/test5
:version
HTTP/1.1
0
答案 0 :(得分:2)
cva.push_back((tok.substr(0, pos)).c_str());
cva.push_back((tok.substr(pos+1, std::string::npos)).c_str());
这部分是未定义的行为。
cva
是const char *
本地指针的向量。您在此处调用临时对象c_str()
。此临时std::string
对象立即超出范围,并在表达式结束时被销毁,此时const char *
的内部内容不再有效。这个指向被破坏对象内部内容的指针被添加到cva
向量中,稍后会尝试打印它,因此会出现未定义的行为。