带有 string_view returns 垃圾的正则表达式
regex with string_view returns garbage
在 std::string_view
上匹配正则表达式工作正常。但是当我 return 匹配子字符串时,它们由于某种原因而死了。 std::string_view
参数在函数范围结束时被销毁,但它指向的内存有效。
我希望 std::match_results
指向初始数组而不进行任何复制,但我观察到的行为表明我错了。
是否可以在不为子字符串额外分配的情况下使该函数工作?
#include <tuple>
#include <regex>
#include <string_view>
#include <iostream>
using configuration_str = std::string_view;
using platform_str = std::string_view;
std::tuple<configuration_str, platform_str> parse_condition_str(std::string_view conditionValue)
{
// TODO: fix regex
constexpr const auto ®exStr =
R"((?:\'$\(Configuration\)\s*\|\s*$\(Platform\)\s*\'==\'\s*)(.+)\|(.+)')";
static std::regex regex{ regexStr };
std::match_results<typename decltype(conditionValue)::const_iterator> matchResults{};
bool matched =
std::regex_match(conditionValue.cbegin(), conditionValue.cend(), matchResults, regex);
(void)matched;
std::string_view config = matchResults[1].str();
std::string_view platform = matchResults[2].str();
return { config, platform };
}
int main()
{
const auto &stringLiteralThatIsALIVE = "'$(Configuration)|$(Platform)'=='Release|x64'";
const auto&[config, platform] = parse_condition_str(stringLiteralThatIsALIVE);
std::cout << "config: " << config << "\nplatform: " << platform << std::endl;
return 0;
}
https://godbolt.org/z/TeYMnn56z
CLang-tydy 显示警告:支持指针的对象将在完整表达式结束时被销毁
std::string_view platform = matchResults[2].str();
手动指定具有偏移量和长度的指针会产生理想的结果:
std::string_view config{conditionValue.data() + matchResults.position(1), matchResults.length(1)};
std::string_view platform{conditionValue.data() + matchResults.position(2), matchResults.length(2)};
https://godbolt.org/z/cGjs39Ehq
但是问题仍然存在,为什么子匹配上的 .str()
方法 returns 是临时的并导致垃圾。
例如,让我们看下面一行:
std::string_view config = matchResults[1].str();
这里,matchResults
的类型是std::match_results
, and [1]
is its std::match_results::operator[]
, which returns an std::sub_match
。
但是,.str()
是它的 std::sub_match::str()
,其中 returns 一个 std::basic_string
。
这个返回的临时 sting 对象将在 full-expression 结束时被销毁(感谢@BenVoigt 的更正),即在这种情况下,在 config
初始化之后立即销毁并且有问题的行完成执行。因此,您引用的 Clang 警告是正确的。
到 parse_condition_str()
函数 returns 时,config
和 platform
string-views 都将指向已经被破坏的字符串。
在 std::string_view
上匹配正则表达式工作正常。但是当我 return 匹配子字符串时,它们由于某种原因而死了。 std::string_view
参数在函数范围结束时被销毁,但它指向的内存有效。
我希望 std::match_results
指向初始数组而不进行任何复制,但我观察到的行为表明我错了。
是否可以在不为子字符串额外分配的情况下使该函数工作?
#include <tuple>
#include <regex>
#include <string_view>
#include <iostream>
using configuration_str = std::string_view;
using platform_str = std::string_view;
std::tuple<configuration_str, platform_str> parse_condition_str(std::string_view conditionValue)
{
// TODO: fix regex
constexpr const auto ®exStr =
R"((?:\'$\(Configuration\)\s*\|\s*$\(Platform\)\s*\'==\'\s*)(.+)\|(.+)')";
static std::regex regex{ regexStr };
std::match_results<typename decltype(conditionValue)::const_iterator> matchResults{};
bool matched =
std::regex_match(conditionValue.cbegin(), conditionValue.cend(), matchResults, regex);
(void)matched;
std::string_view config = matchResults[1].str();
std::string_view platform = matchResults[2].str();
return { config, platform };
}
int main()
{
const auto &stringLiteralThatIsALIVE = "'$(Configuration)|$(Platform)'=='Release|x64'";
const auto&[config, platform] = parse_condition_str(stringLiteralThatIsALIVE);
std::cout << "config: " << config << "\nplatform: " << platform << std::endl;
return 0;
}
https://godbolt.org/z/TeYMnn56z
CLang-tydy 显示警告:支持指针的对象将在完整表达式结束时被销毁
std::string_view platform = matchResults[2].str();
手动指定具有偏移量和长度的指针会产生理想的结果:
std::string_view config{conditionValue.data() + matchResults.position(1), matchResults.length(1)};
std::string_view platform{conditionValue.data() + matchResults.position(2), matchResults.length(2)};
https://godbolt.org/z/cGjs39Ehq
但是问题仍然存在,为什么子匹配上的 .str()
方法 returns 是临时的并导致垃圾。
例如,让我们看下面一行:
std::string_view config = matchResults[1].str();
这里,matchResults
的类型是std::match_results
, and [1]
is its std::match_results::operator[]
, which returns an std::sub_match
。
但是,.str()
是它的 std::sub_match::str()
,其中 returns 一个 std::basic_string
。
这个返回的临时 sting 对象将在 full-expression 结束时被销毁(感谢@BenVoigt 的更正),即在这种情况下,在 config
初始化之后立即销毁并且有问题的行完成执行。因此,您引用的 Clang 警告是正确的。
到 parse_condition_str()
函数 returns 时,config
和 platform
string-views 都将指向已经被破坏的字符串。