2010-02-24 6 views
5

Abbiamo un'applicazione C++/MFC che consente agli utenti di personalizzare la formattazione della data tramite i file di configurazione. Non volendo reinventare la ruota, passo la stringa di formato a CTime :: Format ("< format string>") per eseguire la formattazione effettiva. Sotto le copertine, Format chiama una variante della funzione C standard strftime().Chiamare in modo sicuro strftime con stringa di formato non affidabile

Naturalmente, l'utente può inserire accidentalmente una stringa di formato non valida. (Ad esempio, "% s" invece di "% S".) Quando ciò accade, C Run-Time chiama lo Invalid Argument Handler che, per impostazione predefinita, esce dall'app. (Nessuna eccezione da prendere-- solo uscita app.)

La mia domanda è come gestire con garbo questo input non affidabile. In teoria, potrei scrivere il mio parser/validatore per la stringa di formato, ma suonava come una perdita di tempo. Invece, il meglio che potevo venire con era quello di impostare il mio gestore argomento (globale) non validi, che, invece di uscire, genera un'eccezione Argomento non valido:

void MyInvalidParameterHandler(
    const wchar_t* expression, 
    const wchar_t* function, 
    const wchar_t* file, 
    unsigned int line, 
    uintptr_t pReserved) 
{ 
    ::AfxThrowInvalidArgException(); 
} 

Questo non sembra funzionare, e permette al mio modo esplicito catturare (e gestire con garbo) le eccezioni degli argomenti non validi nei casi in cui "prevedo" che si verifichino. Sono preoccupato, tuttavia, che io stia ignorando un contesto globale, in fase di esecuzione, in una grande applicazione al fine di risolvere un problema relativamente "locale". Detesterei che questa soluzione causasse ulteriori problemi altrove.

Questo approccio è ragionevole? O c'è un approccio più pulito per risolvere questo problema?

risposta

3

Se si è interessati a rilevare questo errore solo in determinati orari, è possibile sostituire temporaneamente il gestore parametri non valido e quindi reimpostarlo dopo aver chiamato Formato.

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(MyInvalidParameterHandler); 

// Your try/Format/catch code here 

_set_invalid_parameter_handler(oldHandler); 

Naturalmente, suppongo che sia possibile che se si dispone di più thread nel vostro programma, un altro thread potrebbe finire per chiamare il tuo gestore di parametro non valido, mentre è impostato. Dovresti determinare quanto probabile sia.

Altro che scrivere la propria funzione di convalida, non sono sicuro di come altro si potrebbe fare questo.

+0

Grazie per il suggerimento. Sfortunatamente, la mia app è effettivamente multi-thread, quindi non penso di poter tranquillamente attivare e disattivare il gestore. (Il gestore parametri non valido è globale, anziché specifico del thread.) –

+0

In tal caso, credo che sarà necessario creare una propria funzione di convalida. Non dovrebbe essere così difficile. Se si guarda in strftime.c nel codice sorgente CRT si vedrà una funzione chiamata _expandtime. Contiene un'istruzione case per tutti gli specificatori di formato supportati. Potresti usarlo come base per la tua funzione. – Dustin

+0

Una possibilità è quella di aggiungere il proprio gestore di parametri non valido che non fa nulla. I documenti affermano che se il controllo ritorna alla funzione chiamante restituirà un codice di errore. – Dustin