Conformità STRICT
Alcuni codice sorgente che compilano correttamente potrebbero generare messaggi di errore quando si abilita il controllo dei tipi STRICT . Le sezioni seguenti descrivono i requisiti minimi per la compilazione del codice quando è abilitato STRICT . Sono consigliati passaggi aggiuntivi, soprattutto per produrre codice portatile.
Requisiti generali
Il requisito principale è che è necessario dichiarare tipi di handle corretti e puntatori di funzione anziché basarsi su tipi più generali. Non è possibile usare un tipo di handle in cui è previsto un altro. Ciò significa anche che potrebbe essere necessario modificare le dichiarazioni di funzione e usare più cast di tipi.
Per ottenere risultati ottimali, il tipo HANDLE generico deve essere usato solo quando necessario.
Dichiarazione di funzioni all'interno dell'applicazione
Assicurarsi che tutte le funzioni dell'applicazione siano dichiarate. L'inserimento di tutte le dichiarazioni di funzione in un file di inclusione è consigliato perché è possibile analizzare facilmente le dichiarazioni e cercare i tipi di parametro e restituiti che devono essere modificati.
Se si usa l'opzione del compilatore /Zg per creare file di intestazione per le funzioni, tenere presente che si otterranno risultati diversi a seconda che si sia abilitato il controllo dei tipi STRICT . Con STRICT disabilitato, tutti i tipi di handle generano lo stesso tipo di base. Con STRICT abilitato, generano diversi tipi di base. Per evitare conflitti, è necessario ricreare il file di intestazione ogni volta che si abilita o si disabilita STRICT o si modifica il file di intestazione per usare i tipi HWND, HDC, HANDLE e così via, anziché i tipi di base.
Tutte le dichiarazioni di funzione copiate da Windows.h nel codice sorgente potrebbero essere state modificate e la dichiarazione locale potrebbe non essere aggiornata. Rimuovere la dichiarazione locale.
Tipi che richiedono cast
Alcune funzioni hanno tipi o parametri restituiti generici. Ad esempio, la funzione SendMessage restituisce i dati che possono essere un numero qualsiasi di tipi, a seconda del contesto. Quando viene visualizzata una di queste funzioni nel codice sorgente, assicurarsi di usare il cast del tipo corretto e che sia il più specifico possibile. L'elenco seguente è un esempio di queste funzioni.
Quando chiami SendMessage, DefWindowProc o SendDlgItemMessage, devi prima eseguire il cast del risultato per digitare UINT_PTR. È necessario eseguire passaggi simili per qualsiasi funzione che restituisce un valore LRESULT o LONG_PTR , in cui il risultato contiene un handle. Ciò è necessario per scrivere codice portatile perché le dimensioni di un handle variano a seconda della versione di Windows. Il cast (UINT_PTR) garantisce la conversione corretta. Il codice seguente mostra un esempio in cui SendMessage restituisce un handle a un pennello:
HBRUSH hbr;
hbr = (HBRUSH)(UINT_PTR)SendMessage(hwnd, WM_CTLCOLOR, ..., ...);
Il parametro CreateWindow e CreateWindowExa volte viene usato per passare un identificatore di controllo intero (ID). In questo caso, è necessario eseguire il cast dell'ID in un tipo HMENU :
HWND hwnd;
int id;
hwnd = CreateWindow(
TEXT("Button"), TEXT("OK"), BS_PUSHBUTTON,
x, y, cx, cy, hwndParent,
(HMENU)id, // Cast required here
hinst,
NULL);
Ulteriori considerazioni
Per ottenere il massimo vantaggio dal controllo dei tipi STRICT , sono disponibili linee guida aggiuntive da seguire. Il codice sarà più portatile nelle versioni future di Windows se si apportano le modifiche seguenti.
I tipi WPARAM, LPARAM, LRESULT e LPVOID sono tipi di dati polimorfi. Contengono diversi tipi di dati in momenti diversi, anche quando il controllo dei tipi STRICT è abilitato. Per ottenere il vantaggio del controllo dei tipi, è necessario eseguire il cast dei valori di questi tipi il prima possibile. Si noti che i cracker dei messaggi recastno automaticamente wParam e lParam per l'utente in modo portatile.
Prestare particolare attenzione a distinguere i tipi HMODULE e HINSTANCE . Anche con STRICT abilitato, vengono definiti come lo stesso tipo di base. La maggior parte delle funzioni di gestione dei moduli kernel usa tipi HINSTANCE , ma esistono alcune funzioni che restituiscono o accettano solo tipi HMODULE .
Argomenti correlati