A volte succede di scrivere una funzione, che accetti un numero di parametri variabile a seconda del modo con cui viene richiamata nelle varie parti del codice del programma. La soluzione più ovvia, come viene indicato nell'
articolo scritto da
Vladislav Gelfer, è quella di
definire la funzione con tutti i possibili parametri che questa può accettare in modo da prevedere qualsiasi tipo di situazione.
Il problema, in questo caso, è che si richiede più lavoro allo
stack e che il codice diventa praticamente impossibile da leggere dovendo usare molte più righe per fornire tutte le istruzioni da eseguire per ogni parametro. Per evitare questa problematica si potrebbero usare le variabili globali, ma ciò porterebbe ad errori causati da funzioni che operano su variabili con valori, i quali cambiano di volta in volta in modo globale durante l'esecuzione dell'applicazione.
Come dice l'autore,
un'ottima soluzione consisterebbe nell'utilizzare la gestione delle eccezioni strutturata di Windows. Il codice che segue mostra un esempio dell'uso di queste ultime, nel caso in cui ci sia la necessità di utilizzare un parametro in più.
const DWORD EXCEPTION_FETCHPARAM_B = 0x800A0001L;
void Func_Nested(int a)
{ // do some job. At some situation we realize
// that we need another parameter.
// Let's fetch it.
int b;
ULONG_PTR nExceptionParam = (ULONG_PTR) &b;
RaiseException(EXCEPTION_FETCHPARAM_B, 0, 1, &nExceptionParam);
// By now 'b' is filled. Continue our work as usual.
}
void Func_Intermediate(int a)
{ // do some job. At some point call nested function
Func_Nested(a);
}
void Func_Top()
{ // at this point we have all possible parameters.
EXCEPTION_POINTERS* pException;
__try
{ Func_Intermediate(12);
}
__except
(
pException = GetExceptionInformation(),
EXCEPTION_FETCHPARAM_B == pException->ExceptionRecord->ExceptionCode ?
(
ASSERT(1 == pException->ExceptionRecord->NumberParameters),
ASSERT(pException->ExceptionRecord->ExceptionInformation[0]),
*((int*) pException->ExceptionRecord->ExceptionInformation[0]) = 14,
EXCEPTION_CONTINUE_EXECUTION
) :
EXCEPTION_CONTINUE_SEARCH
)
{ // This point must not be reached,
// since we never return EXCEPTION_EXECUTE_HANDLER
}
}