Issue #19315 has been updated by kou (Kouhei Sutou). rhenium (Kazuki Yamaguchi) wrote in #note-23:
I wonder if `RSTRING_PTR()` could instead allocate a read-only copy dedicated for `RSTRING_PTR()`, rather than permanently converting the String away from `STR_SHARED`.
I think the current patch in <https://github.com/ruby/ruby/pull/17045> introduces an unfortunate corner case that could be difficult to reproduce or debug:
How about doing it only when the target `String` is frozen or `STR_TMPLOCK`? We can use https://github.com/ruby/ruby/pull/17045/changes#diff-430d86fdb6c4a558ab0f1b6... for it as @himura467 already mentioned. Do we need it for non frozen `String`?
This also means `RSTRING_RAW_PTR()` is slightly harder to use safely, even when a NUL terminator is not required. For example, in ruby/openssl, there is code that needs a pointer that survives across execution of arbitrary Ruby code: https://github.com/ruby/openssl/blob/c7cdca78f5ee19576113d6d600fd22650f0e37c...
I think that the current `RSTRING_PTR()` for non frozen `String` also has similar situation. If arbitrary Ruby code changes the target `String`, pointer returned by `RSTRING_PTR()` may be invalid: ```c char *ptr = RSTRING_PTR(str); // Run "str << large_str" in Ruby // ptr may be invalid here. ``` So I don't feel that this is a new problem of new `RSTRING_RAW_PTR()` API. ---------------------------------------- Feature #19315: Lazy substrings in CRuby https://bugs.ruby-lang.org/issues/19315#change-117468 * Author: Eregon (Benoit Daloze) * Status: Open ---------------------------------------- CRuby should implement lazy substrings, i.e., "abcdef"[1..3] must not copy bytes. Currently CRuby only reuse the char* if the substring is until the end of the buffer. But it should also work wherever the substring starts and ends. Yes, it means RSTRING_PTR() might need to allocate to \0-terminate, so be it, it's worth it. There is already code for this (`SHARABLE_MIDDLE_SUBSTRING`), but it's disabled by default and `RSTRING_PTR()` needs to be changed to deal with this. It seems a good idea to introduce a variant of `RSTRING_PTR` which doesn't guarantee \0-termination, so such callers can then use the existing bytes always without copy. There are countless workarounds for this missing optimization, all not worth it with lazy substring and all less readable: * https://bugs.ruby-lang.org/issues/19314 * https://bugs.ruby-lang.org/issues/18598#note-3 * https://github.com/ruby/net-protocol/pull/14 * Manual lazy substrings which track string + index + length * More but I don't remember all now, feel free to comment or link more urls/tickets. -- https://bugs.ruby-lang.org/