2013-09-29 10 views
6

So che questa domanda è stato chiesto numerose volte nel SO, ma questa è una variazione dal resto.errore C4996: 'std :: _ Copy_impl': chiamata di funzione con parametri che possono essere pericoloso

Compiler Error: Function call with parameters that may be unsafe

Visual Studio Warning C4996

xutility(2227): warning C4996: 'std::_Copy_impl'

mancanza frammento di codice

DWORD dwNumberOfNames = pExportDirectory->NumberOfNames; 
LPDWORD dwNames = (LPDWORD)((LPBYTE)hDLL + pExportDirectory->AddressOfNames); 
std::vector<std::string> exports; 
std::copy(
    dwNames, 
    dwNames + dwNumberOfNames, 
    [&exports, &hDLL](DWORD dwFuncOffset) 
{ 
    std::string fname = std::string((PCHAR)((PBYTE)hDLL + dwFuncOffset)); 
    exports.push_back(fname); 
} 
); 

Errore del compilatore

Errore 1 Errore C4996: 'std :: _ Copy_impl': chiamata di funzione con parametri che possono essere pericolosi - questa chiamata si basa sul chiamante per verificare che i valori passati siano corretti. Per disabilitare questo avviso, utilizzare -D_SCL_SECURE_NO_WARNINGS. Vedere la documentazione su come utilizzare Visual C++ 'A quadri Iteratori' C: \ Program Files (x86) \ Microsoft Visual Studio 11.0 \ VC \ include \ xutility 2176

Domanda

Considerando, C4996, significa che la funzione è stata contrassegnata per essere deprecata Dov'è il problema?

  1. È l'uso di std :: copy, che MS ritiene non sicuro e sarebbe deprecato?
  2. È perché ho usato std::copy con un C Array?
  3. È a causa del modo in cui utilizzo l'espressione Lambda?
  4. Se std :: copy è deprecato, qual è l'alternativa, se ho bisogno di essere portatile.

Nota

lo so, come eliminare l'avviso, ma sono curioso di sapere, la causa principale del problema?

Inoltre, altrettanto importante per me sapere, il modo portatile per gestire questo problema senza compromettere la qualità del codice.

+1

Il terzo parametro a std :: copia dovrebbe essere un iteratore di uscita, ma si dispone di un lambda che non restituisce un iteratore. –

+0

(1): con 'std :: copy', non si è sicuri di avere un" posto "sufficiente per output Iterator, quindi c'è un possibile overflow del buffer. – Jarod42

+0

@ Jarod42 Vedere la mia risposta qui sotto, e se si utilizza un 'std :: back_inserter' con un contenitore standard, non si hanno i problemi di overflow. –

risposta

6

Non sta chiamando std::copy secondo il MSDN: http://msdn.microsoft.com/en-us/library/x9f6s1wf.aspx

che la funzione di firma è questo:

template<class InputIterator, class OutputIterator> 
    OutputIterator copy( 
     InputIterator _First, 
     InputIterator _Last, 
     OutputIterator _DestBeg 
    ); 

Non c'è posto per un funtore/lambda lì.

Non stai chiamando std::copy_if sia: http://msdn.microsoft.com/en-us/library/ee384415.aspx

template<class InputIterator, class OutputIterator, class BinaryPredicate> 
    OutputIterator copy_if(
     InputIterator _First, 
     InputIterator _Last, 
     OutputIterator _Dest, 
     Predicate _Pred 
    ); 

Come avrete iteratore di uscita, né il tuo predicato restituisce un bool.

Sembra che si desidera std::transform: http://msdn.microsoft.com/en-us/library/391xya49.aspx

template<class InputIterator, class OutputIterator, class UnaryFunction> 
    OutputIterator transform( 
     InputIterator _First1, 
     InputIterator _Last1, 
     OutputIterator _Result, 
     UnaryFunction _Func 
    ); 

e si dovrebbe essere la restituzione del valore desiderato nella iteratore di uscita. Quindi sarà qualcosa del genere:

std::transform(
    dwNames, 
    dwNames + dwNumberOfNames, 
    std::back_inserter(exports), 
    [&hDLL](DWORD dwFuncOffset) // This lambda is WRONG 
{ 
    // THIS LINE IS WRONG 
    std::string fname = std::string((PCHAR)((PBYTE)hDLL + dwFuncOffset)); 
    return fname; 
} 
); 

Il mio lambda è sbagliato. È necessario l'ingresso degli elementi della propria matrice (non sono sicuro del tipo) come argomento al lambda, e torno quello che vuoi inseriti nel exports vettoriale.

Probabilmente anche non conoscevo back_inserter. È nell'intestazione <iterator>. Vedi qui: http://msdn.microsoft.com/en-us/library/12awccbs.aspx e qui: http://www.cplusplus.com/reference/iterator/back_inserter/

Questo potrebbe non essere il 100% della risposta, ma con quello, penso che tu possa arrivare dove vuoi andare.

+0

Sembra quasi che stia usando 'std :: for_each' –

1

Non std::copy è di per sé, credo che il problema è quello di utilizzare LPDWORD per fare la copia che rende Visuall C++ pensa che si sta facendo copia stringa C perché LPDWORD non è un iteratore controllato.

http://msdn.microsoft.com/en-us/library/ttcz0bys(v=vs.120).aspx

+0

Apprezzo la tua risposta. Hai una ragione per la tua speculazione? L'errore del compilatore si riferisce a std :: _ Copy_impl, non a uno strcpy. E dove vedi una chiamata a strcpy? – Abhijit

+0

Il messaggio, presente nella questione, suggerisce fortemente che * è * 'std :: stesso copy' che viene messo in guardia, e anche, la questione non usa' 'char * (non dove l'avvertimento è, in ogni caso). – hvd

+0

Ho esattamente questo avviso con strcpy, strlen, ecc. Ho appena controllato, questo avviso è perché non si usa un iteratore verificato. –

Problemi correlati