-- Leo's gemini proxy

-- Connecting to it.omarpolo.com:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini;lang=it

Funzioni simpatiche


Ci sono alcune funzioni della libreria standard di C che meritano il titolo di “simpatiche”, ovvero un mal di testa continuo per la portabilità.


A differenza di altri linguaggi, C è standardizzato, il che significa che esistono diversi standard e diverse implementazioni. Gli standard più famosi sono ANSI C e POSIX (nelle sue varie edizioni.)


Il lato negativo di avere uno standard rispetto ad una implementazione di riferimento è che se lo standard è vago, gli implementatori possono fare quello che vogliono. Questo è il caso in particolare di basename(3) e dirname(3).


basename(3)

dirname(3)


Entrambe le funzioni prendono e ritornano una stringa


char	*basename(char *);
char	*dirname(char *);

Ma lo standard non dice nulla su come si debbano comportare. Esistono due implementazioni (che io conosca):


una che modifica l’argomento passato

una che usa un buffer interno e non modifica l’argomento passato


Da quello che posso vedere il comportamento classico della funzione nei BSD è il secondo, con FreeBSD che di recente ha cambiato “fazione”. glibc (almeno stando al manuale) è strana:


> With glibc, one gets the POSIX version of basename() when <libgen.h> is included, and the GNU version otherwise.


(con “POSIX” version credo intendano la versione che usa un buffer di memoria interno.)


Questo perché non possiamo avere cose belle, immagino.


Il vantaggio di non modificare la stringa passata è che in C le stringhe letterali sono allocate in un’area di sola-lettura: provare a modificarle risulta in un segfault. (I lettori più attenti potrebbero obiettare che una stringa letterale è un ‘const char *’ e che passarla a una funzione che prende un ‘char *’ dovrebbe provocare un warning.)


Il vantaggio della seconda opzione è la thread-safety.


In sostanza, se si ha a che fare con dirname e/o basename bisogna assumere che la stringa passata venga modificata e che il valore ritornato possa venire cambiato da una seguente chiamata alla stessa funzione, e quindi mantenere copie delle stringhe.


L’ispirazione per questo post è stata data dall’essere stato fregato (di nuovo) da queste due funzioni nel giro di pochi giorni: prima nel ricevere una patch e poco dopo nel fare una PR.


P.S.: cari gruppi che si occupano dei vari standard — che di sicuro leggete il mio blog — ora che funzioni come ctime_r, strerror_r ecc. esistono, cosa aspettate a richiedere, per dire, l’esistenza di dirname_r? Se lo fate oggi magari in dieci anni la situazione sarà diversa ;)


$BlogIt: funzioni-simpatiche.gmi,v 1.1 2021/10/20 07:41:39 op Exp $

-- Response ended

-- Page fetched on Fri May 17 04:22:49 2024