条件跳转或移动取决于 std::wistringstream 的未初始化值
Conditional jump or move depends on uninitialised value(s) for std::wistringstream
我从 cppreference.com 窃取了以下代码片段
并将其用于 wchar_t
:
的用法
#include <string>
#include <iostream>
#include <sstream>
template <typename T>
struct test_seq {};
template <>
struct test_seq<char> {
std::string operator()() {
return "1\n2\n3\n4\n5\n6\n7\n";
}
};
template <>
struct test_seq<wchar_t> {
std::wstring operator()() {
return L"1\n2\n3\n4\n5\n6\n7\n";
}
};
int main(int, char **) {
using char_t = wchar_t;
std::basic_istringstream<char_t> input;
test_seq<char_t> seq;
input.str(seq());
int sum = 0;
for (std::basic_string<char_t> token; std::getline(input, token);) {
sum += std::stoi(token);
}
std::cout << "The sum is: " << sum << "\n";
return 0;
}
毫不奇怪,将char_t
更改为char
不会影响sum
的值并且程序成功退出。
无论如何,通过 valgrind --leak-check=full --leak-resolution=med --track-origins=yes ...
使用 valgrind 分析两个版本 会导致 wchar_t
的巨大错误日志 例,而 char
一切都很好。 Valgrind 的错误日志如下:
==1== Memcheck, a memory error detector
==1== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1== Command: ./a.out
==1== Parent PID: 0
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x55715C7: __wmemchr_avx2 (memchr-avx2.S:250)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4EE8B80: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4F7AD08: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4F7AD0D: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4F7AD17: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Use of uninitialised value of size 8
==1== at 0x4F7AD25: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4EE8BA7: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
[...]
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x55713EE: __wmemchr_avx2 (memchr-avx2.S:58)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Use of uninitialised value of size 8
==1== at 0x5571437: __wmemchr_avx2 (memchr-avx2.S:92)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x5571443: __wmemchr_avx2 (memchr-avx2.S:97)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x557144C: __wmemchr_avx2 (memchr-avx2.S:102)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Use of uninitialised value of size 8
==1== at 0x4F7AD70: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4F572EA: std::__cxx11::basic_stringbuf<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::underflow() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8D69: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1==
==1== HEAP SUMMARY:
==1== in use at exit: 0 bytes in 0 blocks
==1== total heap usage: 4 allocs, 4 frees, 76,920 bytes allocated
==1==
==1== All heap blocks were freed -- no leaks are possible
==1==
==1== For counts of detected and suppressed errors, rerun with: -v
==1== ERROR SUMMARY: 48 errors from 20 contexts (suppressed: 0 from 0)
这是怎么回事?我是否滥用了 std::istringstream
和/或 std::getline
?
这可能已经解决了 Valgrind 错误 https://bugs.kde.org/show_bug.cgi?id=388862。
尝试从当前源构建 Valgrind http://valgrind.org/downloads/repository.html 并查看错误是否仍然存在。
我从 cppreference.com 窃取了以下代码片段
并将其用于 wchar_t
:
#include <string>
#include <iostream>
#include <sstream>
template <typename T>
struct test_seq {};
template <>
struct test_seq<char> {
std::string operator()() {
return "1\n2\n3\n4\n5\n6\n7\n";
}
};
template <>
struct test_seq<wchar_t> {
std::wstring operator()() {
return L"1\n2\n3\n4\n5\n6\n7\n";
}
};
int main(int, char **) {
using char_t = wchar_t;
std::basic_istringstream<char_t> input;
test_seq<char_t> seq;
input.str(seq());
int sum = 0;
for (std::basic_string<char_t> token; std::getline(input, token);) {
sum += std::stoi(token);
}
std::cout << "The sum is: " << sum << "\n";
return 0;
}
毫不奇怪,将char_t
更改为char
不会影响sum
的值并且程序成功退出。
无论如何,通过 valgrind --leak-check=full --leak-resolution=med --track-origins=yes ...
使用 valgrind 分析两个版本 会导致 wchar_t
的巨大错误日志 例,而 char
一切都很好。 Valgrind 的错误日志如下:
==1== Memcheck, a memory error detector
==1== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1== Command: ./a.out
==1== Parent PID: 0
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x55715C7: __wmemchr_avx2 (memchr-avx2.S:250)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4EE8B80: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4F7AD08: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4F7AD0D: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4F7AD17: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Use of uninitialised value of size 8
==1== at 0x4F7AD25: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4EE8BA7: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
[...]
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x55713EE: __wmemchr_avx2 (memchr-avx2.S:58)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Use of uninitialised value of size 8
==1== at 0x5571437: __wmemchr_avx2 (memchr-avx2.S:92)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x5571443: __wmemchr_avx2 (memchr-avx2.S:97)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x557144C: __wmemchr_avx2 (memchr-avx2.S:102)
==1== by 0x4EE8B54: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Use of uninitialised value of size 8
==1== at 0x4F7AD70: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::_M_append(wchar_t const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8B93: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1== Conditional jump or move depends on uninitialised value(s)
==1== at 0x4F572EA: std::__cxx11::basic_stringbuf<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::underflow() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x4EE8D69: std::basic_istream<wchar_t, std::char_traits<wchar_t> >& std::getline<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >(std::basic_istream<wchar_t, std::char_traits<wchar_t> >&, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >&, wchar_t) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==1== by 0x109128: main (test.cxx:31)
==1==
==1==
==1== HEAP SUMMARY:
==1== in use at exit: 0 bytes in 0 blocks
==1== total heap usage: 4 allocs, 4 frees, 76,920 bytes allocated
==1==
==1== All heap blocks were freed -- no leaks are possible
==1==
==1== For counts of detected and suppressed errors, rerun with: -v
==1== ERROR SUMMARY: 48 errors from 20 contexts (suppressed: 0 from 0)
这是怎么回事?我是否滥用了 std::istringstream
和/或 std::getline
?
这可能已经解决了 Valgrind 错误 https://bugs.kde.org/show_bug.cgi?id=388862。
尝试从当前源构建 Valgrind http://valgrind.org/downloads/repository.html 并查看错误是否仍然存在。