Perché strdup considerato male

Ho visto alcuni manifesti affermando che strdup è male. C’è un consenso su questo? Io l’ho usato senza alcun colpevole sentimenti e non vedo alcun motivo perché è peggio di utilizzo malloc/memcpy.

L’unica cosa che posso pensare potrebbe guadagnare strdup una reputazione che i chiamanti uso improprio (ad es. non si rendono conto che è necessario liberare la memoria restituita; tenta di strcat alla fine di un strdup sotto stringa). Ma poi malloc sotto le stringhe non sono esenti dalla possibilità di un uso improprio o.


Grazie per le risposte e mi scuso con quelli che considerano la domanda inutile (voti per chiudere). In sintesi delle risposte, sembra che non c’è la sensazione generale che strdup è male di per sé, ma un generale consenso sul fatto che è possibile, come in molte altre parti del C, essere utilizzati in modo improprio o unsafely.

Non c’è ‘corretto’ rispondere davvero, ma per il bene di accettare, ho accettato @nneoneo risposta – potrebbe ugualmente sono state @R..’s risposta.

  • Questa domanda non era per caso chiesto il mio commento precedente era?
  • In riferimento ai commenti su Può un ciclo causare problemi con l’assegnazione in C.
  • sì, ma io avevo visto lo stesso sentimento espresso altrove, che è il motivo per cui ho creato una domanda, piuttosto che a chiedere a voi.



6 Replies
  1. 31

    Due motivi posso pensare:

    1. Non è strettamente ANSI C, ma piuttosto POSIX. Di conseguenza, alcuni compilatori (es. MSVC) scoraggiare l’uso (MSVC preferisce _strdup), e tecnicamente il C standard potrebbe definire la propria strdup con una semantica diversa dal str è un prefisso riservato. Così, ci sono alcuni potenziali questioni di portabilità con il suo utilizzo.
    2. Nasconde la sua allocazione di memoria. La maggior parte delle altre str funzioni non allocare la memoria, in modo che gli utenti potrebbero essere ingannati (come dici tu) a credere che la stringa restituita non ha bisogno di essere liberata.

    Ma, a parte questi punti, credo che un uso attento di strdup è giustificato, come si può ridurre la duplicazione del codice e fornisce una bella realizzazione per il comune idiomi (come strdup("constant string") per ottenere un mutevole, per restituire la copia di una stringa letterale).

  2. 19

    La mia risposta è piuttosto sostenere strdup e non è peggio di qualsiasi altra funzione in C.

    1. POSIX è un standard e strdup non è troppo difficile da attuare se la portabilità diventa un problema.

    2. Se per liberare la memoria allocata da strdup non dovrebbe essere un problema se qualcuno preso un po ‘ di tempo per leggere la pagina man e capire come strdup opere. Se uno non capisce come funziona, è molto probabile che la persona sta andando a rovinare qualcosa, questo è applicabile a qualsiasi funzione, non solo strdup.

    3. In C, di memoria, & la maggior parte delle cose sono gestiti dal programmatore, in modo strdup non è peggio di dimenticare di gratis malloc‘de memoria, non riuscendo a null terminare una stringa, un utilizzo non corretto stringa di formato in scanf (e invocando comportamenti indefiniti), l’accesso ai penzoloni puntatore etc.

    (Volevo postare come commento, ma non si potrebbe aggiungere in un unico commento. Quindi, inviato come risposta).

  3. 10

    In realtà non ho ancora sentito strdup descritto come il male, ma alcune possibili ragioni per alcune persone non piace:

    1. Non C standard (ma è in POSIX). Tuttavia trovo questo motivo stupido, perché è quasi una riga di funzione per aggiungere su sistemi che, in mancanza di esso.
    2. Ciecamente la duplicazione di stringhe in tutto il luogo piuttosto che in luogo, quando possibile, sprechi di tempo e di memoria e presenta casi di fallimento in codice che potrebbe altrimenti essere a prova di errore.
    3. Quando si ha bisogno di una copia di una stringa, è molto probabile che hai effettivamente bisogno di più spazio per modificare o costruire su di esso, e strdup non dare che.
  4. 5

    Penso che la maggior parte della preoccupazione per strdup deriva da problemi di sicurezza per quanto riguarda il buffer di oltre corre, e non formattata correttamente le stringhe. Se un non-terminazione null stringa viene passata a strdup è possibile allocare una stringa di lunghezza indefinita. Non so se questo può essere specificamente sfruttato in un attacco, ma in generale è buona, sicura, pratica codifica per utilizzare solo le funzioni di stringa che prendere una lunghezza massima, invece di basarsi sul carattere null da solo.

    • Se un non-terminazione null stringa viene passata a qualsiasi funzione che si aspetta una stringa con terminazione null, il programmatore ha preso una cantonata male.
    • Eppure è accaduto, questo è il motivo per utilizzare strncpy invece di strcpy, quando la sicurezza è una preoccupazione seria. Questo può accadere anche con imprevisti input dell’utente, o file danneggiati. In generale è meglio sicurezza di poter contare su un esplicito lunghezza piuttosto che la terminazione null di una stringa.
    • Per la maggior parte degli scopi pratici, io non uso strncpy(). Ciò non garantisce la terminazione null. Se si copia un 5 byte word in un 20 KiB buffer scrive anche 20475 valori null. Né il comportamento è accettabile per me. Normalmente, assicurarsi so per quanto tempo la stringa e utilizzare memmove() o (a volte) memcpy(); io ho le recidive e l’uso strcpy(), ma solo se so che c’è abbastanza spazio. (Se è una consolazione, strncat() è peggio di strncpy(); non lo uso mai!) Se non so la lunghezza massima della stringa, non riesco a manipolare in modo sicuro. Non riesco a capire da dove può essere troncato anche.
    • Un array di char senza una terminazione null non è una “stringa” per definizione. Lei non si aspetta fopen() a lavorare quando si dà un URL http invece di un percorso. Qualsiasi programmatore che dà un normale array di char di una funzione che si aspetta una stringa dovrebbe DOCUMENTARSI o non essere permesso di rimanere nel raggio di 100 metri di qualsiasi codice di produzione. Saranno molto probabilmente anche dimenticare di controllare il ritorno di malloc() NULL.
    • Se sei preoccupato per la sicurezza della vostra gestione delle stringhe (che si dovrebbe sempre essere), che è una migliore idea di non buttare raw str* chiamate in tutto il codice. La scrittura di una stringa libreria di gestione che si prende cura di tutti i problemi tipici ed esclusivamente questo. Naturalmente, se siete più preoccupati per tali cose stupide come “considerazioni sulle prestazioni” quando si utilizza strlen() invece di my_strlen(), poi avrai quello che ti meriti.
    • Io non sono sicuro che questa risposta ha un senso. strdup garantisce spazio a sufficienza per includere il carattere di terminazione. L’alternativa è il programmatore che scrive news = malloc(strlen(olds) + 1); strcpy(news,olds) e possibile dimenticare il +1 (e strncpy non necessariamente aiutare se ha dimenticato di pensare alla necessità per il null).

  5. 2

    Molte persone, ovviamente, non lo so, ma io personalmente trovo strdup male per diversi motivi,

    • il principale dei quali si nasconde l’assegnazione. L’altro str* funzioni e la maggior parte delle altre funzioni standard non richiedono free successivamente, strdup sembra abbastanza innocuo e si può dimenticare di pulire dopo di esso. dmckee suggerito basta aggiungere alla tua lista mentale delle funzioni che necessitano di una pulizia dopo, ma perché? Non vedo un grande vantaggio sopra la riduzione di cui due di media lunghezza linee per una breve.

    • Si alloca la memoria nell’heap di sempre e con la C99 è (è 99?) VLAs, è ancora un altro motivo per utilizzare solo strcpy (non c’è nemmeno bisogno di malloc). Non sempre si riesce a fare questo, ma quando si può, si deve.

    • Non è parte dello standard ISO (ma è parte dello standard POSIX, grazie Wiz), ma questo è davvero un piccolo punto di R.. accennato che possono essere aggiunti facilmente. Se devi scrivere programmi portabili, non sono sicuro di come sarebbe a dire se è stata già definita o no, però…

    Questi sono, naturalmente, un paio di mie ragioni, di nessun altro. Per rispondere alla tua domanda, non c’è consenso, che io sappia.

    Se si sta scrivendo programmi solo per se stesso e trovare strdup nessun problema, quindi c’è molto meno motivo per non usarlo più se si sta scrivendo un programma per essere letto da molte persone di molti livelli di abilità ed età.

    • Il vostro primo punto di screditare praticamente l’intero linguaggio C? Se non ti liberi strdup() non ti liberi proprie cose. Perché è diverso? Come VLA, in particolare sulla dimensione arbitraria stringhe è in cerca di guai e indefinito comportamenti senza avvisi. Come per l’ultimo punto: non è standard: Sì è. È parte dello standard POSIX. Non è solo una parte della ISO standard C – che è abbastanza portatile per la maggior parte delle persone.
    • proprio le cose sono accattivanti, strdup si fonde. Questo era il punto. Grazie per il punto sul standardness.
    • Sono quasi tentata di downvote dal momento che sono in disaccordo con la maggior parte di quello che dici. Non voglio, ma andrò su record come dire che penso che la tua obiezione non è davvero rilevante. Dato il numero di volte che le persone commettono errori simulazione strdup() — di solito da dimenticare per allocare spazio sufficiente per la terminazione null — avere una funzione di libreria è molto più sensibile di rendere tutti reinventare la (7-line) funzione di se stessi.
    • 7-line? Ho sempre pensato come uno o due… char *new = malloc(strlen(old)+1); return new ? strcpy(new, old) : 0;
    • Meglio con memcpy, no? ie. size_t len = strlen(old) + 1; char *new = malloc(len); return new ? memcpy(new, old, len) : 0;
    • Scritto senza condizionali, 7 linee: prototipo di funzione (nell’intestazione), definizione di funzione malloc, se, memcpy, la restituzione, la parentesi graffa di chiusura.
    • non zero terminare la stringa e la memoria da malloc può contenere zero byte…
    • sì che è il motivo per il + 1 in size_t len = strlen(old) + 1;

  6. 1

    Il mio motivo per antipatia strdup, che non è stato menzionato, è che si tratta di allocazione delle risorse, senza una coppia naturale. Proviamo per un gioco stupido: io dico malloc, si dice free. Io dico open dici close. Io dico create dici destroy. Io dico strdup dici ….?

    In realtà, la risposta a strdup è free di corso, e la funzione sarebbe stato meglio denominato malloc_and_strcpy di rendere chiaro. Ma molti programmatori C non la penso così e si dimentica che strdup richiede il suo opposto o “fine” free deallocare.

    Nella mia esperienza, è molto comune trovare perdite di memoria nel codice che chiama strdup. E ‘ una funzione pari e dispari, che combina strlen, malloc e strcpy.

Lascia un commento