Question about the function "Form" that return a format string

Hello, I would want to ask about the Form function in ROOT.
I read from the TString class reference page that this function is not very safe to format strings, as the string can be overwritten. I encountered such issue once or twice.

From my understanding, the function uses vsnprintf to create a formatted string with the correct number of characters, then return the string as a char pointer. This approach is quite similar to a post on stack-overflow, which I modify a bit as shown below:

template <typename ... Args>
char* strformat (
		const char* format,
		Args ... args )
{
	int required_length = 1 + std::snprintf( nullptr, 0, format, args ... );
	if( required_length<1 )
		return nullptr;
	unsigned int string_length = required_length;
	char* return_string = (char*)malloc( required_length * sizeof(char) );
	std::snprintf( return_string, string_length, format, args ... );
	return return_string;
}

I don’t understand why the latter function (strformat) doesn’t seem to have the return string overwritten, or at least, in my bugged case when I replace Form by strformat, the strings are no longer overwritten. Is it because the return string is declared differently in these two cases?

Thank you very much,
Hoa.

I think @Axel can give more details about this

1 Like

From my understanding, the function uses vsnprintf

It is not about the vsnprintf but about what it is writing. The function strformat in your post is safe but requires the user to free the returned buffer (or incur a memory leak). The Form free function on the other hand is closer to the following tweak (with the buffer over-run actually handled) of strformat:

static char* return_string = (char*)malloc( required_length * sizeof(char) );

So it does not requires the user/caller to delete the buffer but is also always writting in the same (thread local) buffer.

The better solution is usually to use:

TString str;
str.Form(...);

which uses the 'TString` created before hand as the buffer and thus does not risk overwritting.

2 Likes

Thank you very much, I understand it now.