이 코드는 IncludeOS github page에서 가져옵니다. 다른 헤더 파일없이 컴파일되도록 약간 수정했습니다. IncludeOS의 find
함수가 너무 장황하기 때문에이를 단순화하고 싶습니다. 그러나 수정 후, 코드는 예상했던 것과 다르게 동작합니다.clang ++ 메모리 sanitizer가 사용 초기화되지 않은 값을보고합니다.
다음은 간단한 설명입니다. 이 코드는 HTTP 헤더를 구문 분석하는 데 사용됩니다. 머리글 필드는 이름 - 값 쌍입니다. vector<pair<string, string>>
으로 표시됩니다. find
함수는 헤더의 필드 이름 위치를 찾는 데 사용되며 has_field
은 헤더에 특정 필드 이름이 존재하는지 확인하는 데 사용됩니다.
main
함수에는 네 개의 요소가 필드에 추가됩니다. six
은 fields에 없습니다. 그러나 has_field
은 true를 반환합니다.
gdb
으로 오류를 추적하려고했습니다. 그러나 나는 산출물의 바다에서 길을 잃었다. 나는 다소 흥미로운 메시지를 찾았다.
표준 : __ uninitialized_copy < 거짓 > :: __ uninit_copy < __gnu_cxx :: __ normal_iterator < 표준 : : 쌍 < 표준 : __ cxx11 :: 표준 < 문자, 표준 : : char_traits < 문자 > :: 할당 <를 basic_string 숯불 > >, 표준 : __ cxx11 :: < CHAR, 표준 : char_traits <CHAR>, 표준 : 할당 <CHAR> > > CONST의 * STD : 벡터 < 표준 : 쌍 :: __ cxx11 < 성병 basic_string :: basic_string < 문자, 표준 : : char_traits < 문자 <, 표준 : : 할당 < 문자 > >, 표준 : __ cxx11 :: basic_string < 문자, 표준 : : char_traits < 문자 >, 표준 : : 할당 < 문자 > > > , 표준 : : 할당 < 표준 : : 쌍 < 표준 : __ cxx11 :: basic_string < 문자, 표준 : : char_traits < 문자 <, 표준 : : 할당 < 문자 > >, 표준 : __ cxx11 :: basic_string < 문자, 표준 : : char_traits <char>, std :: allocator <char> > > > > >, 표준 : 쌍 < 표준 : __ cxx11 :: basic_string < CHAR, 표준 : char_traits <CHAR>, 표준 : 할당 <CHAR> >, 표준 : __ cxx11 :: < 숯불 basic_string, STD :: char_traits <CHAR>, 표준 : 할당 <CHAR> > > > * (__first = {제 = "하나"초 = "1"} __last =
{= 제 < 오류 판독 변수 : 없다 게으른 문자열 만들기 주소 0x0 및 0이 아닌 길이 >, 초 = ""}, __result = 0x61bf00)
내가 뭐가 잘못 알아 clang
소독제를 사용했다. 메모리 소독제 만 흥미로운 보고서를 보여줍니다.,
clang++ -std=c++17 -O1 -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer main.cc
/a.out
리포트
초기화되지 않은 값 _ZNSt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_EC2IRA6_KcRA2_S8_Lb1EEEOT_OT0_'` '함수의 스택 프레임에서'ref.tmp '의 할당에 의해 생성 된 실행.
최적화 수준을 -O3
으로 설정하면 아무 것도 표시되지 않습니다.
#include <algorithm>
#include <iostream>
#include <vector>
#include <experimental/string_view>
using Headers = std::vector<std::pair<std::string, std::string>>;
using string_view = std::experimental::string_view;
Headers::const_iterator find(Headers fields, const string_view field) {
if (field.empty()) return fields.cend();
//-----------------------------------
return
std::find_if(fields.cbegin(), fields.cend(), [field](const auto _) {
return std::equal(_.first.cbegin(), _.first.cend(), field.cbegin(), field.cend(),
[](const auto a, const auto b) { return std::tolower(a) == std::tolower(b); });
});
}
bool has_field(Headers fields, const string_view field)
{
return find(fields, field) != fields.cend();
}
int main()
{
Headers fields;
fields.emplace_back("one", "1");
fields.emplace_back("two", "2");
fields.emplace_back("three", "3");
fields.emplace_back("four", "4");
std::string s = "six";
if (has_field(fields, s))
std::cout << s << " is in " << "fields" << std::endl;
return 0;
}
가 초기화되지 않은 값에 대해 알고하지 않습니다,하지만 당신은 값으로'fields' 벡터를 전달하고, 따라서 'has_field'이 벡터의 다른 사본에 반복자를 비교합니다. –
@BoPersson 네 말이 맞아. 값으로 전달 된 컨테이너에 반복자를 반환하는 것은 매우 잘못입니다. 여기에 관련된 stackoverflow 질문입니다. https://stackoverflow.com/questions/10113572/does-passing-containers-by-value-invalidate-iterators – JohnKoch