sprintf_s() 因“调试断言失败”错误而失败

Posted

技术标签:

【中文标题】sprintf_s() 因“调试断言失败”错误而失败【英文标题】:sprintf_s() fails with "debug assertion failed" error 【发布时间】:2016-06-17 15:35:24 【问题描述】:

问题可能很简单,但经过数小时的研究和编辑后我无法让它工作,所以我在这里发布我的问题。

我正在尝试制作一个函数,它接收一位整数或两位整数,并在将其转换为两位整数格式(例如 7 到 07)后将其作为字符串返回。

char *to_two_digits(int num) 

    char num_str[4];

    sprintf(num_str, "%d", num);

    int length = sizeof(*num_str) / sizeof(char);

    static char *return_string;

    if (length == 1) 

        sprintf_s(return_string, "0%d", num);

        return return_string;
    
    else if (length == 2) 
        *return_string = *num_str;
        return return_string;
    
    else 
        printf("Error! Number cannot be represented as a two-digit.");
        exit(1);
    

运行 sprintf_s() 函数时函数失败,错误提示:

--------------- Microsoft Visual C++ 运行时库-----------

调试断言失败!

文件:minkernel\crts\ucrt\src\appcrt\stdio\output.cpp

线路:261

表达式:格式!= nullptr

有什么问题,我该如何解决?提前谢谢你。

【问题讨论】:

你的minimal reproducible example在哪里,我们怎么能看到它?提前谢谢你。 【参考方案1】:

您将一个空指针传递给sprintf_s 函数。你在这一行声明的指针

static char *return_string;

从未初始化为指向任何东西。由于它被声明为静态,因此它被预初始化为零(而不仅仅是具有不确定的值)。

这就是消息告诉您的内容。 sprintf_s 代码中有一个 assert 用于检查您是否没有传递空指针,这就是触发的原因。

你应该传入一个指向函数可以写入的缓冲区的指针。但是由于您使用的是 C++,因此您实际上应该为此使用 std::string,然后您可以从函数中返回它而无需静态变量。

【讨论】:

谢谢你的回答,我会尝试使用字符串类而不是使用静态变量。但是,我是否也知道应该进行哪些编辑才能使用静态变量使代码正常运行? @jake 你需要让指针真正指向某个东西。就像一个适当大小的字符缓冲区。例如:static char return_string[100]; static char return_string[100]; 是我之前尝试过的代码之一,并且产生了同样的错误。知道为什么吗? 我没有收到那个错误,@jake。这样对我来说效果很好。 Live demo。我什至在断言处于活动状态的调试版本中对其进行了测试。编译器会自动确定缓冲区的大小,因为它正在调用sprintf_s 的模板版本。该代码还有另一个故障点,编译器警告:返回局部变量地址num_str【参考方案2】:

正如它所说的那样——你将一个空指针传递给sprintf_s

就是return_string,你没有初始化它来指向任何东西,更不用说一个足够大的缓冲区来获得实际结果了。它不是不确定的值,而是由于static 而肯定是一个空指针,但这种保证对您没有帮助。

实际上使用static 进行这样的内存管理并不是一个好主意,因为您的函数是 100% 不可重入的。通常你会让你的用户传入一个足够大的缓冲区来获得结果,并让调用范围处理缓冲区的生命周期。

【讨论】:

以上是关于sprintf_s() 因“调试断言失败”错误而失败的主要内容,如果未能解决你的问题,请参考以下文章

从发布模式更改为调试模式时出现“调试断言失败”错误

c++错误:调试断言失败

调试断言失败错误

调试断言失败

在没有进行任何代码更改的情况下突然出现错误“调试断言失败错误”。 (在 C++ 代码中)

断言失败:闯入调试器