0

在子函数中调用 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 像那样崩溃?

4

1 回答 1

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);
}
于 2013-05-13T09:19:42.357 回答