2012-11-22 118 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