c - sprintf() 出错:'__builtin___sprintf_chk' 可能会在目标末尾写入终止 nul
问题描述
我正在尝试按照本指南为 RX 制作工具链。该指南使用以下工具:
GCC-4.6.4
binutils-2.23.52
gdb-7.6
newlib-2.0.0
当我运行第一个make
时,我遇到了这个错误:
../../binutils-2.23.52/binutils/prdbg.c:500:20: 错误: '__builtin___sprintf_chk' 可能会在目标 [-Werror=format-overflow=]
sprintf (buf , "%ld", (long) vma);
然后我打开代码并导航到这应该有错误的部分:
static void
print_vma (bfd_vma vma, char *buf, bfd_boolean unsignedp, bfd_boolean hexp)
{
if (sizeof (vma) <= sizeof (unsigned long))
{
if (hexp)
sprintf (buf, "0x%lx", (unsigned long) vma);
else if (unsignedp)
sprintf (buf, "%lu", (unsigned long) vma);
else
sprintf (buf, "%ld", (long) vma); // <-- this line
}
// ... // some code below
我搜索并找到了这些问题:question 1和question 2。我知道这个溢出错误是因为缓冲区不够大,无法包含所有数据。但是这个链接指出两者都long
具有unsigned long
相同的存储大小(8 字节)。
我尝试替换long
为unsigned long
并且它通过了,这个文件上没有更多错误(所以我认为下面的代码没有相关错误)但我认为这不是一个好方法。
所以,我真的不明白为什么long
会导致错误而unsigned long
不会。还是我误解了什么?谢谢您的帮助。
ps:实际上在这个错误之前,我首先遇到了这两个错误(在其他文件中):
- 跌倒
- 负移
但它们与这个错误无关(我修复了它们)所以我跳过了。
解决方案
unsigned long的存储大小可能是 8 个字节,但字符串中的十进制表示可能更长!
例如,2^32
适合 4 个字节,但字符串表示"4294967296"
需要 11 个字节(注意隐含的零字节作为字符串终止符)!因此,您需要为目标提供大于 8 个字节的缓冲区sprintf()
。
一般来说,ceil(log_10(max_value_of_datatype)) + 1 (zero byte)
十进制字符串表示需要字节(根据符号的不同,减号可能需要一个额外的字节)。
对于 64 位无符号值,这会导致
ceil(log_10(2^64)) + 1 = 21 bytes
64 位有符号的结果相同:ceil(log_10(2^63)) + 1 + 1 (for minus sign) = 21 bytes
.
对于 32 位无符号值,这会导致ceil(log_10(2^32)) + 1) = 11 bytes
,而对于 32 位有符号值,必要的空间是ceil(log_10(2^31)) + 2) = 12 bytes
!
推荐阅读
- c++ - 在合并两个数组时,如果将数组大小作为用户的输入,那么它很好,但是如果使用 sizeof() 运算符,那么它是分段错误吗?
- python - 在html中使一个按钮触发另一个按钮
- laravel - 错误无法解析的依赖解析[参数#0 [
$session ]] 包 darryldecode / laravelshoppingcart - android - 通过 Retrofit 获取 API 时出错,但相同的 API 正在与邮递员一起使用
- python - 只做第一个和最后一个真条件,
- linux - Wine 中的 VB 脚本不返回 RND 函数的值
- python - 填充形状多边形的内部
- postgresql-9.6 - 需要用公式在两行之间添加和划分
- c++ - 在成员函数中访问类模板参数
- ssh - ssh 是否使用 sni 标头以及 SNI 如何注入 ssh 隧道连接