`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). 나는 전화 할 생각 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::assign, vector::assign, deque::assign, list::assign,와 forward_list::assign.

  • Libc ++는 이러한 모든 테스트 사례를 작동시킵니다.
  • Libstdc ++는 forward_listsegfaults를 제외하고 모두 작동 합니다.
  • MSVC 라이브러리에 대해 모르겠습니다.

libstdc ++의 segfault는 이것이 UB라는 희망을줍니다. 그러나 나는 libc ++과 libstdc ++가 적어도 일반적인 경우 에이 작업을 수행하기 위해 많은 노력을 기울이는 것을 보았습니다.


ASan으로 테스트 케이스를 컴파일하거나 Valgrind에서 실행 했습니까? 코드가 액세스 위반을 유발하는지 여부를 추측 할 수는 있지만 정의보다는 실제로 실제로 작동 할 수 있습니다.
Konrad Rudolph

1
"basic_string의 멤버 함수 또는 연산자에서 예외가 발생하면 해당 함수 또는 연산자는 basic_string 오브젝트에 다른 영향을 미치지 않습니다." -이렇게하면 기존 스토리지가 해제되기 전에 스토리지 할당이 발생하므로 할당에 실패하지 않고 예외가 발생하지 않고 예외가 발생합니다 *this. 그러나 기존 스토리지가 재사용되는 것을 막을 수있는 것은 없습니다.이 경우 스토리지를 복사하는 의미가 지정되지 않기 때문에 지정되지 않습니다.
Sam Varshavchik


2
언급 된 시퀀스 컨테이너의 경우 [tab : container.seq.req]assign요구 사항 을 전제로 위반하기 때문에 UB 입니다.
호두

답변:


8

assign문자열 에서 비 const 멤버 함수를 호출하면 ( ...) 포인터에 [...] 포인터 [...]가 해당 요소 에 대해 무효화 됩니다. 이는 위반 전제 조건assign[s, s + n)이 정의되지 않은 동작하므로, 유효 범위입니다.

참고 string::operator=(string const&)자동 할당 무 조작하기 위해 특별히 언어가 있습니다.


1
그렇다면 무효화 지점과 전제 조건을 유지해야하는 시점이 정확히 무엇입니까? 대답은 멤버 함수가 호출 된 후 전제 조건이 유지되어야한다고 가정하는 것 같습니다.
호두

1
@walnut 나는 언어 변호사 (특히 확장 된 C ++ 지식을 가진 사람이 아님)는 아니지만 시나리오를 뒤집을 때 질문을 할 수 있습니다- 실행하는 동안 범위가 무효화 될 수 assign있습니까? 그렇다면 정확히 무효화가 발생할 수있는 시점을 표시하기 위해 assign 구현 내부 에서 특정 지점을 설정해야하며 C ++ 이하 지 않을 것이라고 생각합니다. 그래도 잘못 될 수 있습니다.
Fureeish

2
@Fureeish 나도 모르지만 예를 들어 LWG 이슈 526을 참조하십시오. " 결함이 아닌 "으로 닫혀 있습니다.이 표준은 벡터 자체에있는 std::vector::insert(iterator pos, const T& value)경우 작동 해야하는 클로저에 대한 권장 사항에 언급되어 value있습니다. 해당 참조가 호출에 의해 무효화 될 수 있지만 작동하지 않을 수 있습니다.
호두

1
@walnut는 " 표준이 아니 작업에 권한을 부여하지 않기 때문에 작업에 필요합니다. "- 사랑에게 그것을 . Sooo ... 실제로 어떤 일이 일어나는지 물어볼 가치가 있습니까? 그러한 상황에서 인수 의 사본 을 작성하기 위해 구현이 필요 합니까? 어떻게 현실적으로 구현할 수 있을까요? 컴파일러가 불가능한 작업을 수행하도록 요구하는 표준에 대해 들었습니다. 어쨌든 의견에 감사드립니다!
Fureeish

1
@Fureeish 사실 내 이전 (현재 삭제 된) 예제는 실제로 테스트하려는 것을 테스트하지 않았습니다. 다음 은 필요에 따라 재 할당으로 이동하기 전에 libc ++ 및 libstdc ++가 실제로 복사를 수행하는 고정 된 예입니다.
호두
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.