Huny's Dev Blog
huny.dev

C++ string_view Lifetime: Preserve Queued Text with Owning Strings

Understand why stored string_view text changes. Six C++17 checks compare borrowing, source mutation, substr, null termination, and owning string copies for deferred work.

Hun Jang
Hun Jang Nov 6, 2026

If a stored std::string_view changes after being placed in a work queue or member, check who owns the original buffer and how long it lives. A view is not a string snapshot. Work that must preserve a value beyond the call should copy it into an owning std::string while the source is valid. This C++17 example checks source mutation, subviews, null termination, and queue storage.

Concept illustration of a window onto shared memory and an independently stored copy. It is not an exact memory-layout diagram.

Written and documentation checked: November 6, 2026. Verified on Linux with GCC 14.2.0 in C++17 mode. These are functional checks of a synthetic example, not tests of the user's SDK or a real TTS engine.

A read-only view does not make its source immutable

Microsoft's string_view documentation describes a read-only, non-owning handle to character data. Read-only means the view cannot modify that data; it does not prevent changes through another path.

The example modifies only owner[0]. Without resizing or reallocating, the value observed through the view changes from alpha to Alpha. In contrast, std::string snapshot(view), created before the modification, keeps the original value. A stable address does not imply a preserved value.

Source destruction and pointer invalidation are more dangerous. The C++ working draft's string.view.template.general specifies the relationship between pointer invalidation and views. Returning or storing a view of a temporary or local string does not extend the source's lifetime. Reading the view afterward can be undefined behavior. The draft is a living document; the code below uses only features available in C++17.

Copy into owning storage at the retention boundary

The example's enqueue accepts string_view to read its input temporarily, but stores string in the queue. It separates a borrowing interface from owning storage. The copy must happen while the input is still valid. Converting a dangling view to string does not repair it.

Save the following as string_view_demo.cpp. The vector illustrates ownership; it is not a concurrent work-queue implementation.

These are the verification commands. Leave NDEBUG undefined so the assertions remain active.

Actual output:

Boundaries checked by the six cases

Check
Observation
Application decision
1. Construct a view
data equals the source address
The character data was not copied
2. Modify a source character
The address is unchanged but the view's value changes
Manage mutation timing as well as lifetime
3. Own a snapshot
The original alpha remains
Copy when a snapshot is required
4. view.substr
It still refers into the original buffer
A subview also depends on its source
5. Pointer and length
The array element after the ab range is c
Distinguish a view from a null-terminated C string
6. Queue-owned string
Values survive source modification and local scope exit
Deferred work should own its data

Check 5 examines raw[2] within the array. It does not read prefix[2] beyond the view's range or pass data() alone to a C-string function. The draft's data description warns that null termination is not guaranteed. For a call that requires it, create an owning string as shown and use c_str() while that string remains valid. If the callee retains the pointer, its subsequent lifetime must also be guaranteed.

Check lifetime, mutation, and concurrency separately

Views can suit synchronous processing when the source remains alive, the referenced range remains valid, and reads are safe throughout use. Make ownership explicit at longer-lived boundaries such as deferred callbacks, event queues, and caches. Copying the view object by value or declaring it const does not copy the source data.

These checks do not deliberately read expired memory or dereference views after reallocation. A faulty program printing the expected text by chance would not establish safety. Threads, allocation failure, throughput, and copying costs were not measured either. In a real integration, check when the queue copies its input, when producers reuse buffers, and whether a C API retains pointers beyond the call. Concurrent writes to the source require synchronization separately from lifetime guarantees.

한국어 버전: C++ string_view를 저장했는데 문자열이 바뀔 때: 작업 큐의 소유권과 수명 관리C++ string_view를 저장했는데 문자열이 바뀔 때: 작업 큐의 소유권과 수명 관리

추천 글