問題:一方のマシンで動作し、もう一方のマシンでは失敗する、対応するテストケースを持つメソッドがあります(詳細は以下を参照)。コードに何か問題があり、1台のマシンで偶然に動作する原因になっていると思います。残念ながら、問題を見つけることができません。
std :: stringとutf-8エンコーディングの使用は、私が実際に影響を与えない要件であることに注意してください。C ++メソッドを使用することはまったく問題ありませんが、残念ながら何も見つかりませんでした。したがって、C関数の使用。
方法:
std::string firstCharToUpperUtf8(const string& orig) {
std::string retVal;
retVal.reserve(orig.size());
std::mbstate_t state = std::mbstate_t();
char buf[MB_CUR_MAX + 1];
size_t i = 0;
if (orig.size() > 0) {
if (orig[i] > 0) {
retVal += toupper(orig[i]);
++i;
} else {
wchar_t wChar;
int len = mbrtowc(&wChar, &orig[i], MB_CUR_MAX, &state);
// If this assertion fails, there is an invalid multi-byte character.
// However, this usually means that the locale is not utf8.
// Note that the default locale is always C. Main classes need to set them
// To utf8, even if the system's default is utf8 already.
assert(len > 0 && len <= static_cast<int>(MB_CUR_MAX));
i += len;
int ret = wcrtomb(buf, towupper(wChar), &state);
assert(ret > 0 && ret <= static_cast<int>(MB_CUR_MAX));
buf[ret] = 0;
retVal += buf;
}
}
for (; i < orig.size(); ++i) {
retVal += orig[i];
}
return retVal;
}
テスト:
TEST(StringUtilsTest, firstCharToUpperUtf8) {
setlocale(LC_CTYPE, "en_US.utf8");
ASSERT_EQ("Foo", firstCharToUpperUtf8("foo"));
ASSERT_EQ("Foo", firstCharToUpperUtf8("Foo"));
ASSERT_EQ("#foo", firstCharToUpperUtf8("#foo"));
ASSERT_EQ("ßfoo", firstCharToUpperUtf8("ßfoo"));
ASSERT_EQ("Éfoo", firstCharToUpperUtf8("éfoo"));
ASSERT_EQ("Éfoo", firstCharToUpperUtf8("Éfoo"));
}
失敗したテスト(2台のマシンのうちの1台でのみ発生):
Failure
Value of: firstCharToUpperUtf8("ßfoo")
Actual: "\xE1\xBA\x9E" "foo"
Expected: "ßfoo"
両方のマシンにロケールen_US.utf8がインストールされています。ただし、異なるバージョンのlibcを使用します。コンパイルされた場所に関係なくGLIBC_2.14を搭載したマシンで動作し、他のマシンでは動作しませんが、適切なlibcバージョンがないため、そこでのみコンパイルできます。
いずれにせよ、このコードをコンパイルして、失敗したときに実行するマシンがあります。コードに何か問題があるはずですが、どうなるのでしょうか。C ++メソッド(特にSTL)を指すことも素晴らしいでしょう。ブーストや他のライブラリは、他の外部要件のために避ける必要があります。