| 
 |  | 
The story behind the String component illustrates our pragmatic approach to C++ Standard Components. We based our decision to provide a String component on (1) the knowledge that almost every C program manipulates strings and (2) an AT&T Bell Laboratories internal study showing that string manipulation errors account for a large percentage of the programming errors made by their C programmers. Both assumptions are probably just as valid in your environment.
Consider the following true story from a real computer networking project. Assume machine contains a machine name, such as "nj/garage/edsel", service contains a service name, such as "authorize", and we want to assign to a third variable, dialstring, the result of concatenating machine and service with an intervening dot (the result would be "nj/garage/edsel.authorize" for the illustrative values). Here is the code for Release 1 of the system:
     #include <string.h>
     char *machine, *service;
     char dialstring[32];
     ...
     strcpy(dialstring, machine);
     strcat(dialstring, ".");
     strcat(dialstring, service);
A user crashed Release 1
by using a dialstring longer than 32 characters. Release 2 contained the fix:
     #include <string.h>
     char *machine, *service;
     char dialstring[100];
     ...
     if (strlen(machine)+strlen(service)+1>100)error();
     strcpy(dialstring, machine);
     strcat(dialstring, ".");
     strcat(dialstring, service);
A user crashed Release 2
by using a dialstring longer than 100 characters (it's just as well - if it had been
exactly 100 characters, it would have crashed anyway).
In Release 3, they tried doing
it dynamically:
     #include <string.h>
     #include <malloc.h>
     char *machine, *service;
     char *dialstring;
     ...
     dialstring = malloc(strlen(machine)+strlen(service)+1);
     strcpy(dialstring, machine);
     strcat(dialstring, ".");
     strcat(dialstring, service);
Release 3 crashed at random
times in random places, apparently unrelated to this code.
An extensive debugging
effort finally uncovered the problem -
the amount of memory allocated is short by
one byte (for the null character).
Here is Release 4:
     #include <string.h>
     #include <malloc.h>
     char *machine, *service;
     char *dialstring;
     ...
     dialstring = malloc(strlen(machine)+strlen(service)+2);
     strcpy(dialstring, machine);
     strcat(dialstring, ".");
     strcat(dialstring, service);
Release 4 worked fine in
system test.
In the field, though, it was run on a machine with a very small memory,
and crashed when malloc() returned zero. Here's Release 5:
     #include <string.h>
     #include <malloc.h>
     char *machine, *service;
     char *dialstring;
     ...
     dialstring = malloc(strlen(machine)+strlen(service)+2);
     if (dialstring == 0) error();
     strcpy(dialstring, machine);
     strcat(dialstring, ".");
     strcat(dialstring, service);
Release 5 no longer crashed.
However, it gradually ate up all available memory
after it had been running for long enough.
Another debugging effort traced the problem to its source,
and the fix was
put in for Release 6:
     #include <string.h>
     #include <malloc.h>
     char *machine, *service;
     char *dialstring;
     ...
     dialstring = malloc(strlen(machine)+strlen(service)+2);
     if (dialstring == 0) error();
     strcpy(dialstring, machine);
     strcat(dialstring, ".");
     strcat(dialstring, service);
     ...
     free(dialstring);