是string.assign(string.data(),5)定义明确的还是UB?


11

一位同事想这样写:

std::string_view strip_whitespace(std::string_view sv);

std::string line = "hello  ";
line = strip_whitespace(line);

我说过归来string_view使我先天不安,而且,在我看来,这里的别名看起来像UB。

我可以肯定地说line = strip_whitespace(line)在这种情况下等于line = std::string_view(line.data(), 5)。我相信will call string::operator=(const T&) [with T=string_view],其定义为等同于line.assign(const T&) [with T=string_view],其定义为等同于line.assign(line.data(), 5),定义为执行此操作:

Preconditions: [s, s + n) is a valid range.
Effects: Replaces the string controlled by *this with a copy of the range [s, s + n).
Returns: *this.

但是,这并不能说明出现别名时会发生什么。

我昨天在cpplang Slack上问了这个问题,并得到了不同的答案。在这里寻找超级权威的答案,和/或对真实库供应商实施的经验分析。


我写测试用例string::assignvector::assigndeque::assignlist::assign,和forward_list::assign

  • Libc ++使所有这些测试用例都能正常工作。
  • Libstdc ++使它们都可以工作forward_list,但segfaults 除外。
  • 我不知道MSVC的库。

libstdc ++中的段错误使我希望它是UB。但是我也看到libc ++和libstdc ++都将付出巨大的努力,至少在通常情况下才能使此工作正常。


您是否使用ASan编译了测试用例并/或在Valgrind下运行它们?尽管代码仍可能在实践中而不是按定义运行,但这样可以避免猜测是否会导致代码违反访问权限。
康拉德·鲁道夫

1
“如果basic_string的任何成员函数或运算符引发异常,则该函数或运算符对basic_string对象没有其他影响。” -这会强制在分配现有存储空间之前进行存储空间分配,以便在分配失败的情况下抛出异常,而无需更改*this。但是我看不出有什么办法可以防止重复使用现有存储,在这种情况下,由于复制存储的语义是不确定的,因此这种情况变得不确定。
Sam Varshavchik


2
对于提到的序列容器,它肯定是UB,因为前提条件违反了[tab:container.seq.req]中的assign要求。
胡桃

Answers:


8

除非有几个例外,否则assign在字符串上调用非常量成员函数(即)会使指向其元素的指针无效。这违反了先决条件assign[s, s + n)是一个有效的范围内,所以这是不确定的行为。

请注意,该string::operator=(string const&)语言具有专门用于使自指派成为禁止操作的语言。


1
那么失效点和前提条件必须满足的确切点是什么呢?答案似乎是假设前提条件必须在调用成员函数之后成立。
胡桃

1
@walnut我不是语言律师(也不是具有特别丰富的C ++知识的人),但是当我们推翻您的情况时,我们可以提出一个问题- 执行过程中范围是否可能无效assign?如果是的话,那么我们就必须设置一个特定的点分配到标记的执行时完全失效,可能会发生,我相信这不是C ++会做。我可能是错的。
Fureeish

2
@Fureeish我也不知道,但是例如看到LWG问题526,被关闭为“ 不是缺陷 ”,它在关闭建议中提到std::vector::insert(iterator pos, const T& value)必须value在向量本身中起作用,因为该标准未指定它即使调用可能使该引用无效,也允许它不起作用。
胡桃

1
@walnut“ 必须工作,因为该标准未授予它不工作的许可。 ”- 喜欢它。SOOO ...是值得问发生什么事在实践中?在这种情况下是否需要实现来复制参数?您如何现实地实现它?我听说过标准要求编译器做到不可能的事情-这是其中一种情况吗?无论如何,谢谢您的评论!
狂欢

1
@Fureeish实际上,我之前的示例(现已删除)实际上并未测试我想要测试的内容。是一个固定的示例,显示libc ++和libstdc ++都在需要进行重新分配之前实际进行了复制。
胡桃
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.