Context:
The multithreaded finish, stop, fatal, and warning wrappers deferred raw const char pointers into the evaluation message queue. Temporary caller strings could be destroyed before the main thread consumed the message, while nullable arguments also require preserving the distinction between nullptr and a non-null empty string.
Changes:
- Copy nullable filename, hierarchy, and message arguments before posting each deferred callback.
- Reconstruct the original pointer nullness when invoking the existing single-threaded handlers, including non-null empty strings.
- Add an AddressSanitizer regression with independent warning, finish, stop, and fatal modes covering temporary strings, empty strings, and null arguments.
- Check pointer nullness separately from copied string contents.
Evidence:
- Each wrapper mode fails against origin/master with a heap-use-after-free and passes with this change under AddressSanitizer and C++14.
- A temporary mutation that collapses empty filenames to null is rejected by all four modes with a filename-nullness mismatch.
- Seven adjacent multithreaded tests and focused distribution checks passed during candidate verification.
- clang-format 18.1.8 and git diff --check pass.
Boundary:
The change only owns string lifetime and nullable-string identity across the MT message queue. It does not alter finish, stop, fatal, or warning policy.