在我正在開發的項目中,我們同意只使用返回錯誤代碼(無例外)的函數來處理錯誤。通過參數值檢測
爲了不用調試消息「污染」我的代碼,我正在研究基於儀器的解決方案(受this post的啓發)。
代替使用整數作爲錯誤代碼的,我在一個類封裝它爲:
// File rc.h
class rc
{
public:
rc(int) __attribute__((no_instrument_function));
rc& operator=(rc);
private:
int value;
};
接着定義這些運營商和儀表功能:
// File rc.cc
#include <stdio.h>
#include <time.h>
#include "rc.h"
static FILE *fp_trace;
static int isError;
extern "C"
{
void __attribute__ ((constructor)) trace_begin (void)
{
fp_trace = fopen("trace.out", "w");
isError = 0;
}
void __attribute__ ((destructor)) trace_end (void)
{
if(fp_trace != NULL) {
fclose(fp_trace);
}
}
void __cyg_profile_func_enter (void *func, void *caller) __attribute__((no_instrument_function));
void __cyg_profile_func_exit (void *func, void *caller) __attribute__((no_instrument_function));
void __cyg_profile_func_enter (void *func, void *caller)
{
}
void __cyg_profile_func_exit (void *func, void *caller)
{
if ((fp_trace != NULL) && (isError == 1)) {
fprintf(fp_trace, "x %p %p %lu\n", func, caller, time(NULL));
isError = 0;
}
}
}
rc::rc(int valueIn) :
value(valueIn)
{
}
rc& rc::operator=(rc rcIn)
{
value = rcIn.value;
if (value != 0)
{
isError = 1;
fprintf(fp_trace, "%d\n", value);
}
return *this;
}
然而,在爲了不打印太多的東西,我不想記錄返回代碼爲0的函數調用,因此標記爲isError
。
這可以用下面的例子中:
#include <cstdlib>
#include <ctime>
#include "rc.h"
rc bar(void)
{
rc result(std::rand() % 3);
return result;
}
int main(void)
{
std::srand (std::time(NULL));
rc returnCode(0);
for (int i=0; i<10; ++i)
{
returnCode = bar();
}
return 0;
}
編譯和
g++ -finstrument-functions -g -c -o rc.o rc.cc
g++ -g -c -o test.o test.cc
g++ test.o rc.o -o a.out
./a.out
閱讀給定in the previously mentioned post腳本輸出將導致類似運行:
Error code 2
rc::operator=(rc) at 2016-07-03T18:32:09+0200, called from main (test.cc:32)
這幾乎是我所希望的。但與一個解決方案相比,我只需在rc foo(void)
中添加一個測試來測試輸出是否爲非零,然後記錄錯誤,那麼在發生錯誤的情況下,僅會增加開銷(加上檢查的開銷)希望不會太頻繁),我會添加開銷,由於儀器(加上可能的開銷,由於rc包裝,但我很好)在每次調用...
有沒有解決方案,我couldn沒有想過,在參數爲零的情況下,這不會影響operator=
?由於rc::value
僅在運行時才爲人所知,因此我不認爲具有參數值的模板將專用於value=0
,並且不適用於該情況。會嗎?
還有一個額外的約束:重要的是instrumentation函數是賦值運算符,因爲我想知道調用者,因此我無法添加一些額外的代理級別。
在這最後一點編輯,我想過讓賦值運算符在線的(而不是儀表)和調用的返回碼不爲零的情況下的檢測功能但不能工作爲finstrument-function doc page指出:
此工具也適用於在其他函數中內聯擴展的函數。概要分析調用將指示概念上在何處輸入和退出內聯函數。
因此它沒有指向真正的來電者。
你知道,除非你從頭開始編寫所有的代碼,並且從不使用任何C++庫,否則在程序中你可能會遇到異常。 –
是的,我知道這一點。但我們正在重寫很多東西...... – Vser
一個好的提示是使用負數作爲錯誤代碼,結果的正值(包括0)。這就是Linux系統調用的功能。 –