Sto cercando di sbarazzarmi di alcuni avvertimenti del compilatore che dicono che strcpy, sprintf, ecc. Non sono sicuri. Capisco perché sono insicuri, ma non riesco a pensare a un buon modo per correggere il codice, in uno stile C++.
Ecco un estratto del codice:
extList->names[i]=(char *)malloc(length*sizeof(char));
strcpy(extList->names[i],extName); // unsafe
// strncpy(extList->names[i],extName,length); // also unsafe
Ecco il messaggio:
C4996: 'strcpy': questa funzione o variabile potrebbe essere Non sicura. Prendi in considerazione l'utilizzo di strcpy_s. Per disabilitare la deprecazione, utilizzare _CRT_SECURE_NO_WARNINGS. Vedi la guida in linea per i dettagli.
Non riesco a pensare a un modo sicuro per copiare i dati in C++ senza conoscere la lunghezza delle cose da copiare. So che c'è strlen (), ma non è sicuro dato che presuppone (forse erroneamente) che i dati sono terminati con null.
Anche:
// used to concatenate:
sprintf(extStr,"%s%s",platExtStr,glExtStr);
C4996: 'sprintf': questa funzione o variabile potrebbe non essere sicura. Considera invece Usando sprintf_s. Per disabilitare la deprecazione, utilizzare _CRT_SECURE_NO_WARNINGS. Vedi la guida in linea per i dettagli.
Usare std :: string per concatenare è abbastanza facile, ma poi ho bisogno di ottenere i dati in extStr in qualche modo (e non usando strcpy, lol). La funzione string :: c_str () restituisce un puntatore a dati non modificabili, quindi non posso semplicemente impostare extStr uguale ad esso. (E non sono nemmeno sicuro che se il puntatore c_str () ha bisogno di eliminare lo chiama in seguito? Alloca lo spazio usando "nuovo"?)
Qualche consiglio su questa roba? Questo fa parte di un file di 10.000 righe che non è mio ... quindi non sono proprio entusiasta di riscrivere la cosa in modo C++.
Non hai davvero bisogno di pragmi per disabilitarli.
Per win32/msvc, in ProjectProperties -> Proprietà di configurazione -> C/C++ -> Preprocessore -> Definizioni del preprocessore, aggiungere le seguenti macro:
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
Oppure puoi passare questo nei parametri della riga di comando (-D_CRT_SECURE_NO_DEPRECATE). Probabilmente puoi # definirli all'inizio di certi file * .cpp. Inoltre, ci sono probabilmente più di loro (vedi crtdefs.h - sembra che ce ne siano molti ...). Questi tipi di avvertimenti normalmente ti dicono con quali macro puoi disabilitarli - basta leggere l'output del compilatore.
Ecco un'altra risposta a questa domanda.
#ifdef _MSC_VER
#pragma warning(Push)
#pragma warning(disable : 4996)
#endif
strcpy(destination, source);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
Se eliminare solo gli avvisi è il tuo obiettivo ... semplicemente definisci questo _CRT_SECURE_NO_WARNINGS
e sopprimerà tutti gli avvisi di deprecazione. Ma questo non risolverà i problemi sottostanti con funzioni CRT non sicure.
Se sei in versione visual studio> = 2005 e vuoi correggere questi avvertimenti in modo corretto ... il metodo più semplice è #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
e #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
nel tuo progetto.
senza ulteriori modifiche al codice, è possibile osservare che la maggior parte degli avvisi vengono risolti automaticamente. Definendo questa finestra, verranno chiamate automaticamente le funzioni di sovraccarico sicure per la maggior parte delle funzioni CRT non sicure. Le dimensioni del buffer per gli array statici vengono calcolate automaticamente.
Sebbene i buffer allocati dinamicamente non vengano risolti in questo modo, è necessario correggerli manualmente. Si prega di fare riferimento questo link per ulteriori dettagli.
Di seguito è riportato un modo per correggere il tuo esempio in modo programmatico
strcpy_s(extList->names[i], length, extName);
Sai quanto copiare - hai assegnato spazio per questo!
Sicuramente non copieresti volentieri più dello spazio che hai assegnato?
Preferirei utilizzare un metodo che eviti esplicitamente i sovraccarichi del buffer limitando il numero di elementi copiati. Di ritorno quando ero un programmatore C che usavamo
dest = malloc(len); // note: where did we get len?
if ( dest is null ) panic! // note: malloc can fail
strncpy(dest, src, len);
dest[len-1] =0;
Questo è un po 'disordinato, ed è stato sottolineato che usa strncpy () un metodo che è stato originariamente progettato per i campi a larghezza fissa piuttosto che per le stringhe. Comunque fa male
Esistono metodi come strdup () e strlcpy () che possiamo aiutare.
I miei consigli:
1). Il tuo obiettivo non dovrebbe essere quello di sopprimere gli avvertimenti, ma per rendere il codice robusto.
2). Quando copi le stringhe devi assicurarti che:
Se strlcpy () è disponibile nel tuo ambiente allora potresti usarlo, altrimenti perché non scrivere la tua piccola funzione di utilità? Quindi se ci sono avvertimenti solo in quella funzione che hai localizzato allora problema.
Nel tuo primo esempio, conosci già la lunghezza. Dato che non stai allocando length+1
byte, suppongo che length
INCLUDE il terminatore null. In tal caso, solo std::copy
la stringa: std::copy(extName, extName + length, expList->names[i]);
Nel secondo esempio, supponendo che le stringhe di origine siano terminate con null, è possibile calcolare la lunghezza della stringa di destinazione e utilizzare nuovamente std::copy
per concatenare manualmente, oppure è possibile utilizzare std::string
e std::copy
dai risultati di c_str
nella destinazione (sempre supponendo di aver assegnato spazio sufficiente per esso).
c_str()
non assegna memoria che richiederebbe la cancellazione esterna.
Infine nota che sizeof(char)
sarà sempre uno e quindi è ridondante nel tuo malloc, anche se il numero di bit in quel personaggio potrebbe non essere 8 (Vedi CHAR_BIT
).
Penso che dovresti sostituire tutte le chiamate di funzione se possibile chiamare una tua implementazione. Un buon esempio qui sarebbe una funzione per sostituire strcpy e chiamare la versione specifica del compilatore di strcpy al suo interno. La tua implementazione può quindi essere facilmente modificata per adattarsi a qualsiasi compilatore di tua scelta, in particolare se vuoi aggiungere o modificare piattaforme/compilatori.
Esempio:
char* StringCopy(char* Destination, const char* Source, size_t DestinationSize)
{
#ifdef _MSC_VER
return strcpy_s(Destination, Source, DestinationSize);
#else
if(!(strlen(Source) >= DestinationSize))
return strcpy(Destination, Source);
else
return 0x0;
#endif
}
Se la portabilità non è un problema, puoi usare 'strcpy_s' .
Se questo codice deve essere compilato solo per la piattaforma Windows, è meglio usare la versione protetta di queste funzioni. Tuttavia, se questo codice viene compilato su più piattaforme (linux, Aix ecc.), Allora puoi disabilitare l'avviso nel tuo file di configurazione del progetto di Windows (ad esempio, .vcxproj) utilizzando _CRT_SECURE_NO_WARNINGS oppure, puoi usare uno snippet di codice come questo in luoghi in cui tali funzioni sono state chiamate nel file .cpp.
#if _OS_ == _OS__WINDOWS
//secure function call
#else
//already written code
#endif
come suggerito nel messaggio, usa _CRT_SECURE_NO_WARNINGS per disabilitare questo avviso.
in ProjectProperties -> Proprietà di configurazione -> C/C++ -> Preprocessore -> Definizioni del preprocessore, aggiungere le seguenti macro:
_CRT_SECURE_NO_WARNINGS