我正在使用以下程序,该程序正在崩溃。有人知道它崩溃的原因吗?
/* writes a, b, c into dst
** dst must have enough space for the result
** assumes all 3 numbers are positive */
void concat3(char *dst, int a, int b, int c) {
sprintf(dst, "%08x%08x%08x", a, b, c);
}
/* usage */
int main(void) {
printf("The size of int is %d \n", sizeof(int));
char n3[3 * sizeof(int) + 1];
concat3(n3, 0xDEADFACE, 0xF00BA4, 42);
printf("result is 0x%s\n", n3);
return 0;
}
答案 0 :(得分:13)
你混淆二进制数据的大小(这是sizeof
)给你的大小,以及十六进制的文本表示的大小,这就是你想要存储的内容。
在大多数当前系统上,sizeof(int)
的计算结果为4.因此,缓冲区n3
将能够存储13个字符(3 * 4 + 1 == 13)。
然后,将三个整数格式化为8个字符的十六进制格式,这需要存储3 * 8 + 1 == 25个字符。结果缓冲区溢出导致崩溃。
当您将其格式化为文本(并自行指定字段宽度!)时,显然数据类型int
的大小无关紧要。
答案 1 :(得分:2)
尝试3*2*sizeof(int)+1
,其中2*sizeof(int)
是打印每个字节值int
所需的字节数,以十六进制表示。当然,由于您使用的是%08X
格式并期望固定宽度的结果,因此您应该使用uint32_t
。顺便说一下,你的程序也错误地将0xDEADBEEF
作为int
传递给了它可能不适合的#include <inttypes.h>
#include <stdio.h>
/* writes a, b, c into dst
** dst must have enough space for the result
** assumes all 3 numbers are positive */
void concat3(char *dst, uint32_t a, uint32_t b, uint32_t c) {
sprintf(dst, "%08"PRIX32"%08"PRIX32"%08"PRIX32, a, b, c);
}
/* usage */
int main(void) {
printf("The size of int is %d \n", sizeof(int));
char n3[25];
concat3(n3, 0xDEADFACE, 0xF00BA4, 42);
printf("result is 0x%s\n", n3);
return 0;
}
,从而进入了实现定义的转换为签名类型的领域。
以下是包含这些更正的版本:
{{1}}
答案 2 :(得分:1)
我真的不明白sizeof
在您的代码中有什么要做的。在concat3
中,您尝试将每个提供的整数的文本表示形式打印为8个字符的十六进制字符串:因此所需的缓冲区大小应等于8 * 3 + 1 = 25,sizeof(int)
与此无关。
你好像用int混合了内存中占用的大小,以及它的文本表示的长度(在你的情况下很容易确定,因为它是由sprintf
格式字符串修复的)。
旁注:sprintf
是一个真正不安全的功能,您应该考虑弃用。
答案 3 :(得分:0)
崩溃是因为sizeof(int)
(最有可能在您的系统上)4,这意味着n3
长度为13个字节。然后你尝试写8 + 8 + 8 = 24个字符。
答案 4 :(得分:0)
使用snprintf代替sprintf。想想小猫!
但严重的是,您不应该使用缓冲区指针创建接口,而不能创建长度信息。 concat应该有一个最大长度参数。然后在里面使用snprintf。给concat的长度是sizeof(n3)。
它仍然无效,但也不会崩溃。其他答案解释了如何使功能正确。
(哦,也不要使用gets()。只是因为它在标准库中并不意味着它是好的代码。)