Domanda [SOURCE] Funzione per nome OS

Stato
Discussione chiusa ad ulteriori risposte.
Ultima modifica da un moderatore:
C'e' un PICCOLO bug, grande come una casa:

la tua funzione ritorna il puntatore ad un buffer di memoria che e' stato deallocato all'uscita della funzione!

Ritorni il puntatore al buffer gestito dall'oggetto std::string, oggetto che e' locale alla funzione, e quindi distrutto all'uscita della stessa!

Se per caso ha funzionato, ha funzionato per bonta' divina ;)

Decisamente meglio ritornare direttamente il std::string!
 
C'e' un PICCOLO bug, grande come una casa:

la tua funzione ritorna il puntatore ad un buffer di memoria che e' stato deallocato all'uscita della funzione!

Ritorni il puntatore al buffer gestito dall'oggetto std::string, oggetto che e' locale alla funzione, e quindi distrutto all'usicta della stessa!

Se per caso ha funzionato, ha funzionato per bonta' divina ;)

Decisamente meglio ritornare direttamente il std:;string!
Si tratta di un oggetto allocato nell'heap dinamicamente non nello stack altrimenti non avrebbe senso che a me vada tranquillamente :)
 
Ha ragione alynaa. L'oggetto ret è allocato nello stack della funzione e il buffer di caratteri che contiene la stringa è allocato dinamicamente nello heap. Quando la funzione termina viene richiamato il distruttore di ret, che si preoccupa di deallocare quel buffer di caratteri.
Tu ritorni il puntatore a questo buffer di caratteri, che però viene deallocato: ottieni un undefined behaviour (dangling pointer).

Per risolvere puoi semplicemente ritornare tutto l'oggetto stringa, in questo modo:
Codice:
std::string os(){
    // codice
    std::string ret = "Windows "; 
    // codice
    return ret;
}

Un alternativa safe che però è molto più brutta, perché ti obbliga implicitamente a deallocare qualcosa, è:
Codice:
const char* os(){
    // codice
    std::string ret = "Windows "; 
    // codice
    const char *r = new char[ret.length() + 1]; // lunghezza stringa + 1 per il carattere '\0'
    strcpy_s(r, ret.c_str());
    return r; // ricordati di deletarmi!
}
 
Ultima modifica da un moderatore:
Si tratta di un oggetto allocato nell'heap dinamicamente non nello stack altrimenti non avrebbe senso che a me vada tranquillamente :)
Perfetto, @St3ve te lo ha spiegato nei dettagli ;)

Questo vada tranquillamente e' quello che chiamo funziona per sbaglio ;)

Il fatto che funzioni per sbaglio non vuol dire che funzioni ;) .

Se provi a scrivere del codice che alloca e dealloca un po' di memoria (ad esempio qualche elaborazione con le stringhe), vedrai che dopo un po' la tua stringa conterra della roba strana ;)
 
Preferisco SecureZeroMemory, secondo MSDN, ZeroMemory può essere ottimizzato (fuori). Non usare una macro:
Codice:
OSVERSIONINFO os = {};
_________________________________

Questa funzione restituisce un puntatore a spazzatura.
Basta restituire un std::string, e, se il chiamante decide che vogliono fare c_str(), lasciali fare.
_________________________________

Alcuni sistemi operativi avranno numeri di versione identici. Ad esempio, Windows 8 e Windows Server 2012 sono 6.2. Il metodo raccomandato per distinguerli è quello di utilizzare
Codice:
OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
(vero per Windows 8, falso per Windows Server 2012).
_________________________________

C'è un modo migliore. Leggendo l'onnipotente documentazione, dice:
Per ottenere il numero di versione completa del sistema operativo, chiamare la funzione GetFileVersionInfo su una delle DLL di sistema, come Kernel32.dll, quindi chiamare VerQueryValue per ottenere il sottoblocco \StringFileInfo\ProductVersion delle informazioni sulla versione del file.
Devi perciò chiamare GetFileVersionInfoSize, GetFileVersionInfo, e VerQueryValue.
 
Ultima modifica da un moderatore:
Il fatto che la memoria venga resa disponibile per la scrittura non implica che venga sovrascritta

Neanche attraversare la strada con gli occhi bendati non implica venir investiti ;)
 
  • Mi piace
Reazioni: srsly
Questo è il tipico baco che, se in trodotto per sbaglio in progetti grossi, ti fa uscire pazzo per trovarlo. Ed è proprio perchè è molto probabile che nonostante la deallocazione della memoria (che poi non è una dellocazione reale), immediatamente dopo l'uscita dalla funzione il contenuto della stringa sia ancora disponibile. Quindi la volta che capita il crash è solo raramente riproducibile e questo può richiedere molto tempo di debug.
E' meglio imparare a gestire da subito queste cose, credimi. Perchè poi se ci lavori e qualcuno deve pagarti, si incazzano.
 
Stato
Discussione chiusa ad ulteriori risposte.