2015-09-11 6 views
5

TLDRRileva chiamando delete su variabili di stack (con getto-to-pointer operatore)

C'è un modo, per rilevare in modo statico errore nel codice seguente?

struct Foo 
{ 
    operator const int*() 
    { 
     return &data; 
    } 

    int data; 
}; 

int main() 
{ 
    Foo f; 
    delete f; 
} 

poiché non v'è una conversione da Foo a void * contenente soltanto una conversione definita dall'utente, in realtà è consentito chiamare delete su f.

più storia

nella nostra base di codice, ci fosse un modo veramente stupido di stringhe deserializzare, in pseudocodice

char * buff = bar.loadString(); 
use buff; 
delete buff; 

il modo in cui è stato cambiato, per una funzione del carico basato su modelli, così ora deserializzare sguardi come

bar.load(m_IntMember); 
bar.load(m_StringMember); 

ma tutte le occorrenze (c'era un sacco di loro) di loadString doveva essere cambiato manualmente in questo modo:

string buff; 
bar.load(buff); 
use buff; 

sappiamo tutti che cosa l'errore umano può causare, quindi ci sono posti, in cui il codice è stato erroneamente modificato come

string buff; 
bar.load(buff); 
use buff; 
delete buff;  //notice the delete 

dal momento che stiamo usando un po 'non implementazione standard di string in realtà ha un overloaded const char * operator, che può essere colato a void* che può essere cancellato ...

Vorrei prendere tutti questi errori in fase di compilazione (abbiamo alte prestazioni personalizzato alloca Tors, quindi in fase di esecuzione, è facile danneggiare la memoria senza alcun errore di runtime)

Non posso dichiarare operatore delete globale accettare const char* Non riesco a cancellare temporaneamente eliminare operatore string perché è molto utilizzato, quindi non è in grado di compilare senza di esso (non posso "filtrare" l'errore descritto da tutti gli errori, perché msvc interrompe la compilazione quando si raggiunge una certa quantità di errori)

cosa posso fare?

+0

Non è possibile distinguere. Utilizzare piuttosto un puntatore intelligente. –

+0

'const char *' non è implicitamente convertibile in 'void *' poiché perde 'const'-ness. È implicitamente convertibile in 'const void *', ma non dovrebbe essere un argomento legale per 'delete'. Stai espressamente lanciando da qualche parte? – jamesdlin

+0

@jamesdlin compila bene quando modifico l'esempio per restituire 'const int *' vedi http://ideone.com/aL23m2 – relaxxx

risposta

2

Questo sembra farlo:

#include <iostream> 

struct Foo 
{ 
    Foo() : data(42) {} 

    operator const int*() 
    { 
     return &data; 
    } 

    int data; 

    struct AmbiguousPointerConversion {}; 
    private: operator AmbiguousPointerConversion *() { 
     throw "hi"; 
    } 
}; 

int main() 
{ 
    Foo f; 
    const int *p = f; 
    std::cout << *p << '\n'; 
    delete f; 
} 

compilazione questo con g ++ mi dà:

try.cc: In function ‘int main()’: 
try.cc:25:12: error: ambiguous default type conversion from ‘Foo’ 
    delete f; 
      ^
try.cc:25:12: note: candidate conversions include ‘Foo::operator const int*()’ and ‘Foo::operator Foo::AmbiguousPointerConversion*()’ 
try.cc:25:12: error: type ‘struct Foo’ argument given to ‘delete’, expected pointer 
+1

Entrambe le conversioni probabilmente dovrebbero essere 'const', ma assolutamente identiche. Non vorrai che l'ambiguità intenzionale venga risolta sovraccaricando su 'const'. – MSalters

Problemi correlati