In questo articolo presentiamo un’alternativa al classico strcpy(3) fornito con le libc. In realtà lo strcpy delle libc ha veramente ben poco in comune con quello presentato in questo articolo.

Lo strcpy presentato di seguito infatti utilizza la memoria dinamica, e la alloca automaticamente, in modo da evitare implicazioni di sicurezza all’interno della vostra applicazione.

char *
sz_strcpy(char **dst, ...)
{
        va_list ap;
        const char *src;
        char *newdst, *dcp;
        size_t curLen, catLen, srcLen;

        if (dst == (char **) 0)
                return NULL;

        catLen = 0;
        va_start(ap, dst);
        src = va_arg(ap, char *);
        while (src != NULL) {
                catLen += strlen(src);
                src = va_arg(ap, char *);
        }
        va_end(ap);

        curLen = 0;

        newdst = malloc(curLen + catLen + 2);
        if (newdst == NULL) {
                *dst = NULL;
                return NULL;
        }

        dcp = newdst + curLen;
        va_start(ap, dst);
        src = va_arg(ap, char *);
        while (src != NULL) {
                srcLen = strlen(src);
                memcpy(dcp, src, srcLen);
                dcp += srcLen;
                src = va_arg(ap, char *);
        }
        va_end(ap);
        *dcp = '\0';

        *dst = newdst;
        return (newdst);
}       /* sz_strcpy */

Vediamo alcuni esempi di utilizzo:

  char *s;
  s = NULL;
  sz_strcpy(&s, "stringa", 0);
  printf("%s\n", s);
  free(s);
  char *s;
  s = NULL;
  sz_strcpy(&s, "stringa ", "di ", "esempio ", "2.", 0);
  printf("%s\n", s);
  free(s);
  char *s;
  char *stext = "blurb";
  s = NULL;
  sz_strcpy(&s, "stringa ", "di ", "esempio ", stext, 0);
  printf("%s\n", s);
  free(s);

Ebbene sì, è possibile passare più di un argomento alla funzione, e persino variabili, provvederà lei ad accorparli e a inserirli adeguatamente in memoria e a restituire l’output adatto. Non è possibile però passare la stessa variabile che si sta andando a riempire, ovvero:

  sz_strcpy(&s, "stringa", s, 0)  /* SBAGLIATO */

Questa operazione sarà possibile nella funzione sz_strrecpy() che vedremo in un altro articolo.

Importantissimo: avrete notato che l’ultimo argomento da passare alla funzione e’ sempre 0 (oppure NULL), se non lo fate otterrete garbage a volontà e incorrerete in un undefined behavior (il pc potrebbe esplodere, rivoltarsi contro di voi, spegnersi, bestemmiarvi contro…, oppure potrebbe semplicemente funzionare.. se il sistema operativo provvede ad azzerare la memoria per voi.).

Notate inoltre che la memoria allocata dalla funzione va liberata quando si è finito di usarla altrimenti otterrete memleak che non sono mai simpatici all’interno di un programma.