You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C语言可变参数函数调用sprintf异常,求原因及修正方案

问题分析与修复:可变参数函数调用sprintf的错误

你遇到的问题是C语言可变参数处理里的常见误区——sprintf 不能直接接收 va_list 类型的参数

你当前的代码里,把va_start获取到的argptr直接传给sprintf,这相当于把这个指针本身的内存地址当作第一个可变参数(也就是格式化字符串里的第一个%d)输出了,后面的参数也因为整体错位,导致最后一个出现了异常的0值。

要解决这个问题,你需要使用C标准库中专门为va_list设计的函数变体:vsprintf(或者更安全的vsnprintf)。

修正后的代码

#include <QCoreApplication>
#include <QDebug>
#include <stdio.h>
#include <stdarg.h>  // 必须包含这个头文件,va系列宏的定义都在这里

char __errorLog[100];

void debugMsg(const char *control_string, ...);

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    debugMsg("Este es un mensaje de debug con 5 parametros %d %d %d %d %d",1,2,4,56,57);
    return a.exec();
}

void debugMsg(const char *control_string, ...){
    va_list argptr;
    va_start(argptr, control_string);
    // 替换sprintf为vsprintf,它专门接收va_list类型的参数列表
    vsprintf(__errorLog, control_string, argptr);
    va_end(argptr);
    qDebug() << __errorLog;
}

额外的安全建议

  1. 缓冲区溢出风险:你的__errorLog只有100字节,如果格式化后的字符串长度超过这个值,会导致缓冲区溢出,引发未定义行为。建议改用vsnprintf来限制写入的字节数:

    vsnprintf(__errorLog, sizeof(__errorLog), control_string, argptr);
    

    这个函数会自动截断超出缓冲区大小的内容,避免溢出。

  2. Qt自带的日志方案:既然你用Qt Creator开发,其实可以直接用Qt自带的qDebug(),它本身就支持可变参数,用法和printf几乎一样,还不用自己维护缓冲区:

    qDebug("Este es un mensaje de debug con 5 parametros %d %d %d %d %d",1,2,4,56,57);
    

内容的提问来源于stack exchange,提问作者aarelovich

火山引擎 最新活动