Several key functions in the C string library have the potential to overflow their destination strings. Prestring is a C module which offers an alternative string type which can still be manipulated transparently as a C string, along with methods analogous to the dangerous library methods, except that instead of overflowing, they grow the destination string. However, along with this boon comes the responsibility of a little setup and cleanup. Here is a complete sample (download it here):
#include <stdio.h>
#include "prestring.h"
int main(void)
{
char* blah = string_new("blah");
char* winter = string_new("yesterday was the winter of our discontent; ");
char* yar = string_new("yar");
string_copy(blah, winter);
string_cat(blah, "whew");
puts(blah);
string_printf(&yar, "%d %s %f %x %c", 10, "hello", 1.23, 0xf8, blah[18]);
puts(yar);
string_fget(yar, stdin);
puts(yar);
string_destroy(yar);
string_destroy(winter);
string_destroy(blah);
return 0;
}
The output is:
yesterday was the winter of our discontent; whew 10 hello 1.230000 f8 w 70 [you type a line] [whatever line you typed is repeated]
Growable strings (prestrings) must be created with
string_new and string_destroy must be called
on them when they are no longer in use to free the associated
memory. Library functions convert according to the following
table:
| C string function | Prestring function | Comments |
| strcpy | string_copy | Destination must be addressable |
| strcat | string_cat | Destination must be addressable |
| strlen | string_length | string_length is O(1) instead of O(n) |
| sprintf | string_printf | Must add a & before the first argument |
| fgets | string_fget | Don't need to specify a maximum size |
The above functions take only prestrings for their modified arguments,
but take prestrings and C strings for their const arguments (with the
exception of string_length). All other standard
library functions can be used directly on any mix of prestrings and C
strings.
Never shorten a string by inserting null characters. Instead, use
string_truncate, which cuts off the end of a string to
make the string a specified size. Also never lengthen a string by
overwriting the null terminator. To append a string, use
string_cat, and to append a single character, use
string_ccat.
Q. I replaced some strings with prestrings in my code, and now it's crashing! What happened?
A. First, make sure you've replaced every library function in the
table above that is used on the string with the corresponding prestring
function. Using the C library version of any of these on a prestring is
likely to cause a crash. Also, make sure no function that modifies the
string is growing or shrinking it by inserting or overwriting null
characters. You must use string_truncate and
string_cat/string_ccat for this.
Q. After changing some code to use prestrings, I'm experiencing memory leaks. How do I fix these?
A. Because every prestring is dynamically allocated, you have to
be careful to always call string_destroy on it when you're done
with it. In functions with many return points, this can be tricky. A simple
idiom that you may find helpful is to add a goto label near
the end of the function, after which you destroy the string, and then
change all return statements to gotos, storing the return
value in a local variable:
Before:
int stringStuff() {
char* str = string_new("");
string_fget(str, stdin);
if (str[0] == 'b') {
return 2;
}
if (str[2] == 'a') {
return 7;
}
return 0;
}
After:
int stringStuff() {
char* str = string_new("");
int result;
string_fget(str, stdin);
if (str[0] == 'b') {
result = 2;
goto stringStuffCleanup;
}
if (str[2] == 'a') {
result = 7;
goto stringStuffCleanup;
}
result = 0;
stringStuffCleanup:
string_destroy(str);
return result;
}
A working vsnprintf library function is
required to use string_printf. If you have doubts about whether yours works,
this one does:
The files prestring.h and prestring.c comprise the functionality, and prestring-test.c is a demo, with the archive prestring.tar.gz containing all these:
prestring.tar.gz
prestring.h
(view html)
prestring.c
(view html)
prestring-test.c
(view html)
string_fget more flexible