[sldev] Uses of LLString and std::string ?

Phoenix phoenix at secondlife.com
Wed Jan 23 11:15:42 PST 2008


wow, I've never seen so many Lindens reply on a single thread. Guess  
it shows you what makes a c++ nerd's ears perk. :)

Years ago, before open source, in the long ago time, there was  
LLString. It was a very basic string implementation based on NULL  
terminated char* which would dynamically resize on every operation.  
After secretly using standard containers in our code base for a while  
(they used to be forbidden according to our coding standards) to  
prove they worked on all of our platforms, I began replacing all  
instances of char* APIs with a std::string replacement and typically  
using std::string and std::ostringstream for using and building strings.

This worked all right, but std::string has, as noted by Steve and in  
my humble opinion, at least one fatal flaw -- constructing a  
std::string with NULL crashes. The most mechanical transition to  
reduce crashes was to replace all instances of std::string with  
LLString and magically the crashes disappear.

Sadly, the LLString class is not a good use of inheritance and  
introduces overhead when working with many c++ libraries -- even our  
own. To make matters worse, at least one method does not work with  
narrow and wide characters. All new APIs should be using std::string,  
but the habit of using LLString is hard to break.

Personally, I always use std::string, and wrap char* and c APIs with  
ll_safe_string which is prototyped as:

/**
  * @brief Return a string constructed from in without crashing if the
  * pointer is NULL.
  */
std::string ll_safe_string(const char* in);


What we cold really use is an LLString that provided native utf-8  
support like gtk's ustring.


On 2008-01-23, at 10:08, Richard Nelson wrote:
> Keep in mind that LLString derives from std::string and can be used  
> anywhere a std::string is.  But, as Steve notes, you can't  
> arbitrarily convert a reference to a std::string to a reference to  
> a LLString, so any conversion back to LLString will involve a copy.
>
> Before any C++ purists complain, let me note that std::string does  
> not have a virtual destructor and hence we can never add any member  
> variables or implement a non-trivial destructor in LLString.  It  
> serves merely as a convenient wrapper for std::string that tests  
> for the null char* case, as Steve mentioned, and provides some  
> handy functions (e.g. case-insensitive string comparison) that  
> would otherwise require boilerplate code.
>
> Note that all of the custom functions are implemented as statics,  
> and not member functions.  This is to support the ultimate goal of  
> having LLString simply be a namespace for string helper functions  
> that operate on std::strings.
>
> R.
>
> On Wed, 23 Jan 2008 08:52:22 -0800, Steve Linden  
> <steve at lindenlab.com> wrote:
>
>> Correct, LLString exists specifically to protect against passing a  
>> NULL char* to a function that takes a const std::string&. C++ will  
>> quietly attempt to convert the NULL char* into a std::string  
>> causing a crash.
>>
>> e.g.
>>
>> foo (const std::string& s)
>> {
>> }
>> bar (const char* c)
>> {
>>     foo(c); // crashes if c is NULL
>> }
>> main()
>> {
>>     const char* s = fetchSomeString(); // returns NULL if it fails
>>     foo(s); // crash!
>> }
>>
>> Note: we -still- have thousands of char arrays and char*'s in the  
>> code, and this pattern exists all over the place, especially in  
>> the UI code. We are actively working on eliminating this pattern.  
>> Once we do, we can safely replace LLString with std::string.
>>
>> Because of the expense of converting a std::string to a LLString,  
>> we try to use LLString anywhere we will pass it as a std::string.  
>> However, in the grand scheme of things this is unlikely to be a  
>> significant performance bottleneck so we are not as paranoid about  
>> it as we might be.
>>
>> -Steve
>>
>> Dave Parks wrote:
>>> I believe the point of LLString is to protect against NULL  
>>> pointer assignments.  It's legacy from a time when we used char*  
>>> strings and began mixing in std::string.  Assigning a standard  
>>> string to NULL dereferences NULL, causing a crash.  LLString  
>>> protects against this by checking for NULL on assignment for  
>>> char* strings.
>>>
>>> Alissa Sabre wrote:
>>>> I have a question.
>>>>
>>>> SL viewer uses two data types LLString and std::string, that are
>>>> almost identical.  They are sometimes intermixed.  LLString to
>>>> std::string conversion is by a simple upcasting, but the opposit  
>>>> is by
>>>> a deep copy through a constructor that requires some overhead.
>>>>
>>>> What is the purpose of LLString?  In case it has some, then the  
>>>> next
>>>> question is why LL uses both LLString and std::string?  (Cf. LL  
>>>> never
>>>> uses C++ bool type.)
>>>>
>>>> Assuming there is a good reason to use both LLString and  
>>>> std::string
>>>> in SL viewer, what is the criteria (or guidelines) to choose from
>>>> LLString and std::string?
>>>>
>>>>     Alissa Sabre
>>>> --------------------------------------
>>>> Easy + Joy + Powerful = Yahoo! Bookmarks x Toolbar
>>>> http://pr.mail.yahoo.co.jp/toolbar/
>>>> _______________________________________________
>>>> Click here to unsubscribe or manage your list subscription:
>>>> /index.html
>>>>
>>>
>> _______________________________________________
>> Click here to unsubscribe or manage your list subscription:
>> /index.html
>
>
>
> -- 
> Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
> _______________________________________________
> Click here to unsubscribe or manage your list subscription:
> /index.html

-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 186 bytes
Desc: This is a digitally signed message part
Url : http://lists.secondlife.com/pipermail/sldev/attachments/20080123/7f7cef18/PGP.pgp


More information about the SLDev mailing list