numCheck是1-1000之间的数字。只有当我在charcheck中收集sprintf的结果时,此代码才会给我一个段错误。如果我只是使用sprintf而不使用结果,我不会遇到seg故障。这里发生了什么事?Sprintf分割错误
char * numString;
int charcheck = sprintf(numString, "%d", numCheck);
numCheck是1-1000之间的数字。只有当我在charcheck中收集sprintf的结果时,此代码才会给我一个段错误。如果我只是使用sprintf而不使用结果,我不会遇到seg故障。这里发生了什么事?Sprintf分割错误
char * numString;
int charcheck = sprintf(numString, "%d", numCheck);
您需要为sprintf
提供自己的记忆。另外,不要使用sprintf
,而是snprintf
:
char buf[1000] = {0};
snprintf(buf, 999, ....);
另外,您可以动态分配内存:
char * buf = new char[BUFSIZE];
snprintf(buf, BUFSIZE-1, ...);
/* ... */
delete[] buf;
的第一个参数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
来表示字符串的结尾。
有没有什么办法可以找出我用字符传递的整数的大小,这样我就可以分配正确数量的空间而不是使用像80那样的任意值? – syl
@user只是分配额外的空间可能会更有效率(你可以根据你存储的类型来确定一个数字的最大字符数),因为计算它需要一个'if'级联。你只需计算出你的号码的最大数量小于(例如,如果它小于10(但总是'> 0',请注意你)它是1位数字,如果它小于100则是2位数字等等)。但是,在堆栈中分配空间需要一定的时间(并且在这个时间上有一个非常小的常量),只要你不做类似'char numString [9999999999999]'你应该没问题 –
您需要的结果,如
char numString[50];
int charcheck = sprintf(numString, "%d", numCheck);
在你的情况的sprintf的INTERAL运作都尝试引用NULL这是针对你的情况的指针的默认值分配空间。
作为sprintf
的第一个参数给出的指针预计指向一个内存位置,其中sprintf
应写入格式化的字符串。
在这种情况下,您并未初始化numString
以指向您为格式化字符串分配的某些内存。由于numString
未初始化,因此可能指向任何位置,并且在您尝试将格式化输出写入该位置时会导致分段错误。
最直截了当的事情是使用一个数组如上,例如,
char numString[80] = { };
由Seth,耶稣和Kerrek建议。
我认为最后一个答案是很好的解释:“sprintf的第一个参数预计指向sprintf应该写入格式化字符串的内存位置。”因此,从使用字符数组,这将迫使分配内存的字符串分开,你也可以使用这个:
char *numstring = (char*) malloc(80);
这应该让你明确地释放分配内存时不再需要它。
准确地说,为什么当我不收集结果时,它会工作? – syl
这是未定义的行为。有时候未定义的行为会按照您的预期行事,这可能是最糟糕的情况。 –
为什么你推荐'snprintf'比'sprintf'? – Kevin