在子函数内调用 printf 会导致访问冲突。
程序规模相当大。但我能够将问题隔离到只调用子函数的地步。
我能够通过使用如下文字常量调用 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 像那样崩溃?
错误是我期望 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);
}