2012-11-22 90 views
1

我发现了OSX上vsprintf的奇怪行为。在OS X上的vsprintf:EXC_BAD_ACCESS

这是我的代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
#include <string.h> 
#if defined(WIN32) 
#include <windows.h> 
#define VSNPRINTF _vsnprintf 
#elif defined(LINUX) || defined (DARWIN) 
#define VSNPRINTF vsnprintf 
#include <sys/types.h> 
#include <unistd.h> 
#endif 

char *f(const char *fmt, ...) 
{ 
char *out = NULL; 
const int step = 32; 
int n = -1, lout = step; 
va_list arg; 

if(fmt!=NULL) 
{ 
    va_start(arg, fmt); 
    do 
    { 
    if(!out) 
    { 
    free(out); 
    out = NULL; 
    } 
    out = (char*)malloc(lout + 1); 
    if(!out) break; 
    memset(out, 0, lout + 1); 

    n = VSNPRINTF(out, lout, fmt, arg); 
    if(n == -1 || n + 1 > lout) 
    { 
    lout += step; 
    n = -1; 
    } 
    }while(n == -1); 
    va_end(arg); 
} 

return out; 
} 

int main() 
{ 
char *msg = NULL; 
unsigned long x = 0xDEADBEEF; 

msg = f("%X%X%X%X", x, x, x, x); 
if(!msg) return -1; 

puts(msg); 

return 0; 
} 

函数将返回分配的字符串(字符*)包含格式化文本。它在Linux和Windows上正常工作。它在OSX上返回格式不正确的文本,有时会导致分段错误(EXC_BAD_ACCESS)。顺便说一句,我知道我可以使用vasprintf。

可能是什么问题?

+0

有很多额外的代码,声称“未定义的vsprintf行为”。 – 2012-11-22 08:32:37

+0

调试器是你的朋友,用它逐行检查代码,看看会发生什么。或者运行你的程序直到崩溃。 –

回答

3

您的问题很可能是您多次使用相同的va_list调用vsnprintf。这在某些ABI中不起作用。

查看va_copy的手册页。短版本是这样做的:

 va_list c; 
     va_copy(c, arg); 

     n = VSNPRINTF(out, lout, fmt, c); 
     va_end(c); 
+0

解决。谢谢! – pospec4444

+1

除了使用'va_copy()'(这在MSVC上不支持),'va_start()'和'va_end()'调用可以移动到'VSNPRINTF()'调用之前/之后。 –

+0

@MichaelBurr对。我一直忘记MSVC仍然落后二十年。 va_copy是C99。 – Art