2011-08-25 101 views
10

numCheck是1-1000之间的数字。只有当我在charcheck中收集sprintf的结果时,此代码才会给我一个段错误。如果我只是使用sprintf而不使用结果,我不会遇到seg故障。这里发生了什么事?Sprintf分割错误

char * numString; 
int charcheck = sprintf(numString, "%d", numCheck); 

回答

7

您需要为sprintf提供自己的记忆。另外,不要使用sprintf,而是snprintf

char buf[1000] = {0}; 

snprintf(buf, 999, ....); 

另外,您可以动态分配内存:

char * buf = new char[BUFSIZE]; 
snprintf(buf, BUFSIZE-1, ...); 
/* ... */ 
delete[] buf; 
+0

准确地说,为什么当我不收集结果时,它会工作? – syl

+0

这是未定义的行为。有时候未定义的行为会按照您的预期行事,这可能是最糟糕的情况。 –

+1

为什么你推荐'snprintf'比'sprintf'? – Kevin

1

的第一个参数sprintf必须指向一个有效的缓冲。你有一个char*,但它指向垃圾。

你的代码更改为:

char numString[80] = { }; 
int charcheck = sprintf(numString, "%d", numCheck); 

这样numString实际上指向一个有效的缓冲液(在这个例子中80个字符,所有的元素就是被初始化为0)。

这也将是很好用snprintf这样你就可以通过你的缓冲区,它的大小,这将有助于防止缓冲区溢出:

您从您传递的缓冲区大小减去一个
const int bufsize = 80; 
char numString[bufsize] = { }; 
int charcheck = snprintf(numString, bufsize - 1, "%d", numCheck); 

公告到snprintf,因为您不希望它使用最后一个插槽,您要确保它是NULL来表示字符串的结尾。

+0

有没有什么办法可以找出我用字符传递的整数的大小,这样我就可以分配正确数量的空间而不是使用像80那样的任意值? – syl

+0

@user只是分配额外的空间可能会更有效率(你可以根据你存储的类型来确定一个数字的最大字符数),因为计算它需要一个'if'级联。你只需计算出你的号码的最大数量小于(例如,如果它小于10(但总是'> 0',请注意你)它是1位数字,如果它小于100则是2位数字等等)。但是,在堆栈中分配空间需要一定的时间(并且在这个时间上有一个非常小的常量),只要你不做类似'char numString [9999999999999]'你应该没问题 –

0

您需要的结果,如

char numString[50]; 
int charcheck = sprintf(numString, "%d", numCheck); 

在你的情况的sprintf的INTERAL运作都尝试引用NULL这是针对你的情况的指针的默认值分配空间。

1

作为sprintf的第一个参数给出的指针预计指向一个内存位置,其中sprintf应写入格式化的字符串。

在这种情况下,您并未初始化numString以指向您为格式化字符串分配的某些内存。由于numString未初始化,因此可能指向任何位置,并且在您尝试将格式化输出写入该位置时会导致分段错误。

0

最直截了当的事情是使用一个数组如上,例如,

char numString[80] = { }; 

由Seth,耶稣和Kerrek建议。

我认为最后一个答案是很好的解释:“sprintf的第一个参数预计指向sprintf应该写入格式化字符串的内存位置。”因此,从使用字符数组,这将迫使分配内存的字符串分开,你也可以使用这个:

char *numstring = (char*) malloc(80); 

这应该让你明确地释放分配内存时不再需要它。