You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带可变参数的C函数outputDebug崩溃问题排查求助

Debug Function Crash: Root Cause & Fix

Let's break down why your outputDebug function is crashing and fix it step by step.

Critical Bug Causing the Crash

Your call to vsprintf_s is the main culprit here:

  • You’re passing "%s" as the format string, which only expects one string argument (szPrefix), but you’re also appending the va_list ap afterward. This mismatched parameter count triggers undefined behavior—almost certainly the crash you’re seeing due to invalid memory access.
  • Worse, szPrefix already includes the format placeholders from cpszFormat (like %s in your example call). You need to use szPrefix directly as the format string for vsprintf_s, not "%s".

Additional Potential Issues to Address

  • Type Mismatch in Format Specifier: uintLineNo is an unsigned type, but you’re using %05ld (for signed long integers). This can cause incorrect output or unexpected behavior. Switch to %05u (for unsigned int) instead.
  • Buffer Overflow Risk: szPrefix (80 bytes) and szOut (256 bytes) are small. If your formatted string plus date/time/line info exceeds these limits, sprintf_s/vsprintf_s will throw an error or crash. We’ll adjust this for safety.

Fixed Version of the Function

Here’s the corrected code with clear improvements:

static void outputDebug(unsigned uintLineNo, const char* cpszFormat, ...) { 
    // Expand buffer sizes to handle longer strings safely
    char szPrefix[128], szOut[512]; 
    va_list ap; 
    va_start(ap, cpszFormat); 

    // Fix format specifier for unsigned line number (%05u)
    sprintf_s(szPrefix, sizeof(szPrefix), "%s %s %05u: %s", __DATE__, __TIME__, uintLineNo, cpszFormat); 

    // Use szPrefix as the format string, and pass va_list to fill placeholders
    vsprintf_s(szOut, sizeof(szOut), szPrefix, ap); 

    va_end(ap); 
    OutputDebugString(szOut); 
}

Even Safer Version (Eliminate Buffer Limits)

To completely remove buffer overflow risks, calculate the required memory dynamically:

#include <stdlib.h> // For malloc/free

static void outputDebug(unsigned uintLineNo, const char* cpszFormat, ...) { 
    char* szOut = NULL;
    va_list ap, apCopy;
    int prefixLen, totalLen;

    // Calculate length of the prefix string
    prefixLen = sprintf_s(NULL, 0, "%s %s %05u: %s", __DATE__, __TIME__, uintLineNo, cpszFormat);
    if (prefixLen < 0) return; // Handle formatting error

    // Initialize va_list to calculate total needed length
    va_start(ap, cpszFormat);
    va_copy(apCopy, ap); // Make a copy since va_start can only be used once for calculation

    // Calculate total length including formatted arguments
    totalLen = _vscprintf_s(cpszFormat, apCopy) + prefixLen;
    va_end(apCopy);

    // Allocate buffer (add 1 for null terminator)
    szOut = (char*)malloc(totalLen + 1);
    if (szOut == NULL) {
        va_end(ap);
        return; // Handle allocation failure
    }

    // Build the full formatted string
    sprintf_s(szOut, totalLen + 1, "%s %s %05u: %s", __DATE__, __TIME__, uintLineNo, cpszFormat);
    vsprintf_s(szOut + prefixLen, totalLen - prefixLen + 1, cpszFormat, ap);

    va_end(ap); 
    OutputDebugString(szOut);
    free(szOut); // Clean up allocated memory
}

Why This Fix Works

  • The vsprintf_s call now uses szPrefix (which includes your original format string) as the format specifier, correctly passing the va_list to fill in placeholders from cpszFormat.
  • Fixed the type mismatch for the line number to ensure proper formatting.
  • The safer version calculates exactly how much memory is needed, eliminating any risk of buffer overflow.

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:34:40