: A while ago, there was a discussion of the problems of writing safe
: applications in C, with particular reference to the problems of the
: standard C string library. Does anyone have views on what a better string
: library in C might look like? I had the idea of a structure like a Pascal
: string with a pointer to the bytes in it and a flag to say if they can be
: realloc'ed, and a set of functions similar to the existing ones for these
: string structures.
You could have a look at bounds checking GCC (see my homepage).
If you compile your programs with this modified version of gcc,
then you'll get safe checking for strings and other memory
objects. You could also look at the attached library I wrote.
It doesn't do `safe' strings, but encompasses a number of the
ideas you mention above and is safe to use for reading arbitrarily
long strings from files and other external sources.
Rich.
--------- faststring.h --------------------
/* -*- C -*-
*
* A small fast variable-length string library for C.
* Copyright (C) 1998 Richard W.M. Jones.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef __faststring_h__
#define __faststring_h__
#include <string.h>
struct string {
union {
int length; /* Actual length of string. */
struct string *next; /* When on ``old_strings'' list, this
* stores the next pointer.
*/
} u;
int allocated; /* Nr. bytes allocated to string. */
char *bytes; /* Bytes of string (not necessarily
* NUL-terminated).
*/
Quote:};
static struct string *old_strings = 0;
static int old_strings_size = 0;
#ifndef STRING_MAX_STRING_CACHE
#define STRING_MAX_STRING_CACHE (32*1024)
#endif /* STRING_MAX_STRING_CACHE */
static inline struct string *
string_init (void)
{
struct string *s;
/* If there is a string in the cache, pull it out and
* use it.
*/
if (old_strings != 0)
{
s = old_strings;
old_strings = s->u.next;
old_strings_size -= s->allocated;
}
/* Otherwise, allocate a new string. */
else
{
s = malloc (sizeof (struct string));
if (s == 0) {
perror ("string: malloc");
exit (1);
}
s->allocated = 0;
s->bytes = 0;
}
s->u.length = 0;
return s;
Quote:}
static inline struct string *
string_init_string (const struct string *s)
{
struct string *t = malloc (sizeof (struct string));
if (t == 0) {
perror ("string: malloc");
exit (1);
}
t->bytes = malloc (s->u.length * sizeof (char));
if (t->bytes == 0) {
perror ("string: malloc");
exit (1);
}
t->allocated = t->u.length = s->u.length;
memcpy (t->bytes, s->bytes, s->u.length);
return t;
Quote:}
static inline struct string *
string_init_chars (const char *s)
{
struct string *t = malloc (sizeof (struct string));
if (t == 0) {
perror ("string: malloc");
exit (1);
}
t->allocated = t->u.length = strlen (s);
t->bytes = malloc (t->u.length * sizeof (char));
if (t->bytes == 0) {
perror ("string: malloc");
exit (1);
}
memcpy (t->bytes, s, t->u.length);
return t;
Quote:}
static inline void
string_free (struct string *s)
{
/* If the cache is smaller than the maximum size, then
* push this string into the cache.
*/
if (old_strings_size + s->allocated <= STRING_MAX_STRING_CACHE)
{
s->u.next = old_strings;
old_strings = s;
old_strings_size += s->allocated;
}
/* Otherwise free the string outright. */
else
{
free (s->bytes);
free (s);
}
Quote:}
static inline void
string_append_char (struct string *s, char c)
{
if (s->u.length < s->allocated)
{
do_append:
s->bytes [s->u.length] = c;
s->u.length ++;
}
else
{
s->bytes = realloc (s->bytes,
s->allocated = (s->allocated == 0
? 1
: s->allocated * 2)
* sizeof (char));
if (s->bytes == 0) {
perror ("string: realloc");
exit (1);
}
goto do_append;
}
Quote:}
static inline void
string_truncate (struct string *s)
{
s->u.length = 0;
Quote:}
static inline const char *
string_chars (struct string *s)
{
/* NUL-terminate the string, then adjust its length back
* to normal and return the bytes.
*/
string_append_char (s, '\0');
s->u.length --;
return s->bytes;
Quote:}
static inline char *
string_copy_chars (struct string *s)
{
return strdup (string_chars (s));
Quote:}
static inline int
string_length (const struct string *s)
{
return s->u.length;
Quote:}
typedef struct string *string;
#endif /* __faststring_h__ */
--------- end of faststring.h --------------------
--
- Richard Jones. Linux contractor London and SE areas. -
- Very boring homepage at: http://www.annexia.demon.co.uk/ -
- You are currently the 1,991,243,100th visitor to this signature. -
- Original message content Copyright (C) 1998 Richard Jones. -