Disadvantage #1 seems unnecessary. Instead of this:
s = sdscat(s,"Some more data");
Why not do this?
sdscat(&s,"Some more data");
The latter would make the use-after-free error they're describing impossible. (Disadvantage #2, changing one reference but not others, would remain. And callers would still need to check for NULL if they intend to handle ENOMEM gracefully.)
I assert there's no meaningful performance difference between the two.
This is a common practice in relatively new interfaces like pthread_create.
> And you still want to access the old value if reallocation failed.
If you want to provide commit-or-rollback semantics, you could signal error via return value rather than by replacing s with NULL:
if (sdscat(&s,"Some more data") != SDS_SUCCESS) {
/* failure path; s is unchanged */
} else {
/* s now has "Some more data in it" */
}
but this may be completely useless, depending on the environment(s) in which the library or program is intended to be used. On 64-bit Linux systems with memory overcommit enabled (the default), this failure path essentially shouldn't ever happen. Instead, some process (maybe yours, maybe not) will be picked by the kernel OOM killer. Many programs just use an allocate-or-die interface, as the sds README mentions.
You're right, I wasn't saying that it's the only way to write allocation/assignment.
I was saying that in that case sdscat() matches with sdsnew() style.
I assert there's no meaningful performance difference between the two.