Ray's Knowledge Base

StringViewSet owns its strings, so views into a temporary one dangle

PitfallVerified 28 Sep 2026Holds project: dftracer-utils
Pitfall. The symptom, what causes it, and the fix that was run and seen to work.

Symptom#

A DataFrame expression mask evaluated every row as unknown. The field names saved for the rows printed as garbage:

DBG key [\xef\xbf\xbd] len 1 col [\xef\xbf\xbd] t 2

The code kept views while looping over the result of duql::collect_fields:

for (std::string_view f : collect_fields(node))
    cols.push_back({f, column});   // f is stored for later

Cause#

Despite its name, dftracer::utils::StringViewSet is ankerl::unordered_dense::set<std::string, TransparentStringHash, TransparentStringEqual>: it owns std::string keys and only looks them up with views. The views point into the temporary set, which is destroyed at the end of the loop. (InternedStringViewMap is the type keyed by views.)

Fix#

Keep the set alive as long as the views:

const StringViewSet fields = collect_fields(node);
for (std::string_view f : fields) cols.push_back({f, column});

Or store std::string copies.

Evidence#

  • src/dftracer/utils/dataframe/mask.cpp expr_mask (2026-09-27): with the temporary, tests/dataframe/test_mask.cpp "an expression leaf is evaluated row by row" failed on every row; with the named set it and trace/views/test_duql_paths passed.
  • The type is defined in include/dftracer/utils/core/common/transparent_string_hash.h.