2012-11-16 21 views
0

在子功能中調用printf會導致訪問衝突。printf在子功能中的訪問衝突 - Ansi C90

該程序的規模相當龐大。但我能夠將問題隔離到只有子功能調用的地方。

我能夠通過像這樣的文字常量調用printf來使系統崩潰:printf(「test」)。其他一些人也通過給printf發送一個奇怪的對象來訪問違規行爲 - 這裏不是這種情況。

下面是一些僞代碼:

subfunction() 
{ 
    printf("all works great"); //Access Violation 

    //some other calls here 
} 

void main() 
{ 
    otherfunctions(); // 
    printf("all works great"); 
    subfunction();   
    //some more calls here 
} 

從我stachtrace:

msvcr100d.dll!_chkstk() 
msvcr100d.dll!_write(int fh, const void * buf, unsigned int cnt) 
msvcr100d.dll!_flush(_iobuf * str) 
msvcr100d.dll!_ftbuf(int flag, _iobuf * str) 
msvcr100d.dll!printf(const char * format, ...) 

的代碼是C90代碼,並用VS2010編譯。它應該被視爲C90。 它發生在重構之後,所有_(v)snprintf被替換爲_(v)snprintf_s對應物。我不確定這是否有影響。

我認爲緩衝區在寫入任何內容之前都會被刷新。

如何進一步調查? 我的其他代碼可以觸發什麼系統設置來使printf崩潰?

+0

你可能已經堆棧損壞別處。這段代碼對我來說似乎很好。嘗試使用一些動態代碼分析工具來跟蹤訪問違規。也嘗試在VS中使用「Debug」運行代碼 –

回答

0

錯誤是我期望printf打印一個字符串,但實際上傳遞了一個非字符串給它。

對於Ansi-C,我通常會編寫一個結構來封裝字符串。

typedef struct TString{ 
    char buffer[2000]; 
}TString; 

我傾向於寫:

void mistake(void){ 
    TString str; 
    TStrnig_Construct(&str); 
    prtinf("%s", str); 
    TString_Destuct(&str); 
} 

這是很難發現的我,因爲它真的看起來像str是一個字符串。實際上,str不是一個字符串,而是一個結構。這個錯誤可以在任何地方出現,特別是如果結構的內容與其他信息一起擴展(例如size_t size)。

我應該寫:

void corrected(void){ 
    TString str; 
    TStrnig_Construct(&str); 
    prtinf("%s", str.buffer); 
    TString_Destuct(&str); 
}