Sto scrivendo una libreria che mi piacerebbe essere portatile. Pertanto, non dovrebbe dipendere dalle estensioni di glibc o Microsoft o da qualsiasi altra cosa che non sia nello standard. Ho una bella gerarchia di classi derivate da std :: exception che uso per gestire gli errori in logica e input. Sapendo che un particolare tipo di eccezione è stato lanciato in un particolare file e il numero di riga è utile, ma sapere come l'esecuzione è arrivata sarebbe potenzialmente molto più prezioso, quindi ho cercato modi per acquisire la traccia dello stack.Traccia stack C++ portatile su Eccezione
Sono consapevole che questi dati sono disponibili quando si costruisce contro glibc utilizzando le funzioni a execinfo.h (vedi question 76822) e attraverso l'interfaccia StackWalk in C di Microsoft implementazione ++ (vedi question 126450), ma mi piacerebbe molto di evitare tutto ciò non è portatile
Stavo pensando di attuare questa funzionalità me stesso in questa forma:
class myException : public std::exception
{
public:
...
void AddCall(std::string s)
{ m_vCallStack.push_back(s); }
std::string ToStr() const
{
std::string l_sRet = "";
...
l_sRet += "Call stack:\n";
for(int i = 0; i < m_vCallStack.size(); i++)
l_sRet += " " + m_vCallStack[i] + "\n";
...
return l_sRet;
}
private:
...
std::vector<std::string> m_vCallStack;
};
ret_type some_function(param_1, param_2, param_3)
{
try
{
...
}
catch(myException e)
{
e.AddCall("some_function(" + param_1 + ", " + param_2 + ", " + param_3 + ")");
throw e;
}
}
int main(int argc, char * argv[])
{
try
{
...
}
catch (myException e)
{
std::cerr << "Caught exception: \n" << e.ToStr();
return 1;
}
return 0;
}
E 'una pessima idea? Significherebbe molto lavoro aggiungere blocchi try/catch a ogni funzione, ma posso conviverci. Non funzionerebbe quando la causa dell'eccezione è la corruzione della memoria o la mancanza di memoria, ma a quel punto sei praticamente fregato comunque. Può fornire informazioni fuorvianti se alcune funzioni nello stack non catturano eccezioni, si aggiungono alla lista e rethrow, ma posso almeno garantire che tutte le funzioni della mia libreria lo facciano. Diversamente da una traccia di stack "reale" non otterrò il numero di linea nelle funzioni di chiamata, ma almeno avrei qualcosa.
La mia preoccupazione principale è la possibilità che ciò causi un rallentamento anche quando non vengono effettivamente lanciate eccezioni. Tutti questi blocchi try/catch richiedono un'ulteriore impostazione e rimozione su ogni invocazione di funzione, o sono in qualche modo gestiti in fase di compilazione? O ci sono altri problemi che non ho considerato?
Dai un'occhiata a Herb Sutter's http://www.gotw.ca/gotw/047.htm per un'altra prospettiva. – AJG85