StringRef life cycle

StringRef can be sent in reply as a parameter, like below, but StringRef does not manage its memory directly, So where is it managed?(It will be helpful if you can tell me where the corresponding codes are)

struct TLogPeekReply {
	constexpr static FileIdentifier file_identifier = 11365689;
	Arena arena;
	StringRef messages;
	Version end;
	Optional<Version> popped;
	Version maxKnownVersion;
	Version minKnownCommittedVersion;
	Optional<Version> begin;
	bool onlySpilled = false;

	template <class Ar>
	void serialize(Ar& ar) {
		serializer(ar, arena, messages, end, popped, maxKnownVersion, minKnownCommittedVersion, begin, onlySpilled);
	}
};

Logically TLogPeekReply::arena owns the memory referenced by TLogPeekReply::messages, but there’s actually a bug (that apparently doesn’t manifest) here. arena needs to appear after messages in the call to serializer to ensure that arena really does own the memory. This requirement is described briefly here: foundationdb/flow at master · apple/foundationdb · GitHub.

foundationdb/Arena.h at 37bc41abbbff8626889e75b98d1d20d5476d1900 · apple/foundationdb · GitHub is where the arena would take ownership of the memory referenced by StringRef if the arguments to serializer were ordered correctly.

That’s all mostly only relevant for using TLogPeekReply deserialized from a network message though. If you are constructing TLogPeekReply in order to send it it’s your responsibility to make sure that arena owns the underlying memory.

2 Likes

What if this reply has no arena field? In that case, who will manage the memory for messages? @andrew.noyes

If the reply has a StringRef field and no Arena field, then the underlying memory for the StringRef doesn’t have an owner tied to the reply. Logically that’s a bug or at least highly unconventional. There are various unreliable ways that the memory might be kept alive long enough.

Usually for replies without Arenas we’d either have a Standalone<StringRef> or std::string instead.

Thanks,approve this file