Korzystam z Microsoft Visual Studio Community 2019, V16.5.2. Chcę przetestować inicjalizację listy
Zobacz następujący program testowy:
#include <string>
void foo(std::string str) {}
int main() {
foo( {"str1", "str2"} );
return 0;
}
Kompiluje się bez błędów i ostrzeżeń. Dlaczego?
Daje błąd środowiska wykonawczego: Expression: Transposed pointer range
Czy ktoś może wyjaśnić, co się tutaj dzieje?
Edytować.
Zdemontowałem kod i uruchomiłem go w debuggerze
foo( {"str1", "str2"} );
00F739A8 sub esp,1Ch
00F739AB mov esi,esp
00F739AD mov dword ptr [ebp-0C8h],esp
00F739B3 lea ecx,[ebp-0D1h]
00F739B9 call std::allocator<char>::allocator<char> (0F7136Bh)
00F739BE push eax
00F739BF push offset string "str2" (0F84DB8h)
00F739C4 push offset string "str1" (0F84E2Ch)
00F739C9 mov ecx,esi
00F739CB call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> ><char const *,0> (0F71569h)
00F739D0 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (0F71843h)
00F739D5 add esp,1Ch
Awarie przy pierwszym wywołaniu do konstruktora?
Odpowiedzi:
std::string
ma konstruktor szablonów, który buduje ciąg z pary iteratora początku / końca. Literały łańcuchowe w C ++ przechodzą doconst char*
s. Wskaźniki są iteratorami. Dlatego podczas inicjowania listy wybrano konstruktor pary początkowej / końcowej.Wystąpił błąd w czasie wykonywania, ponieważ dwa wskaźniki w rzeczywistości nie tworzą prawidłowego zakresu, którego nie można ustalić w czasie kompilacji (ogólnie).
źródło
<char const *,0>
. Czy ktoś może to wyjaśnić?template< InputIt > (InputIt first, InputIt last,...)
konstruktor, w którymiter
znajduje się parametr szablonuconst char*
.... i najwyraźniej twoja implementacja ma z jakiegoś powodu drugi parametr liczby całkowitej?std::string
ma przeciążenie konstruktora w postacii to się nazywa bo
"str1"
i"str2"
rozpada się naconst char*
iconst char*
jest akceptowalnym typem iteratora.Występuje awaria, ponieważ „zakres iteratora” przekazany do funkcji jest nieprawidłowy.
źródło
Które używają konstruktora z iteratorami std :: string (6.).
Z [
InputIt
=const char*
].Następnie masz UB, ponieważ zakres
{"str1", "str2"}
jest nieprawidłowy.źródło