你也可以考虑一个辅助函数。
请参阅René Scharfe ( )的提交 45ccef8和提交 60566cb(2016 年 9 月 25 日) 。(由Junio C Hamano 合并 -- --在提交 b1f0a85中,2016 年 10 月 3 日)rscharfe
gitster
它使用COPY_ARRAY
, 一个安全方便的助手来复制数组,补充ALLOC_ARRAY
和REALLOC_ARRAY
.
因此memcpy(temp, a, sizeof(a));
,您将使用COPY_ARRAY(temp, a, 1);
用户只需指定来源、目的地和元素数量;元素的大小是自动推断的。
它检查大小和元素计数的乘积是否溢出。
推断的大小首先传递给st_mult
,这允许在编译时进行除法。
作为基本类型安全检查,它确保源元素和目标元素的大小相同。这也在编译时进行了评估。
COPY_ARRAY
NULL
如果要复制 0 个元素,则可以安全地用作源指针。
该约定在某些情况下用于初始化数组。
Rawmemcpy(3)
不支持它——编译器被允许假设只有有效的指针被传递给它,并且可以
NULL
在这样的调用之后优化掉检查。
#define COPY_ARRAY(dst, src, n) copy_array((dst), (src), (n), sizeof(*(dst)) + \
BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src))))
static inline void copy_array(void *dst, const void *src, size_t n, size_t size)
{
if (n)
memcpy(dst, src, st_mult(size, n));
}
它使用断言构建时依赖关系的宏BUILD_ASSERT_OR_ZERO
作为表达式(@cond
编译时条件必须为真)。
如果条件不成立或编译器无法评估,则编译将失败。
#define BUILD_ASSERT_OR_ZERO(cond) \
(sizeof(char [1 - 2*!(cond)]) - 1)
例子:
#define foo_to_char(foo) \
((char *)(foo) \
+ BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
内联函数st_mult
在commit 320d0b4中引入
static inline size_t st_mult(size_t a, size_t b)
{
if (unsigned_mult_overflows(a, b))
die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
(uintmax_t)a, (uintmax_t)b);
return a * b;
}
st_mult
是检测size_t
溢出的部分辅助函数,包括unsigned_mult_overflows
size_t
对我们提供给和朋友的变量执行计算xmalloc
可能很危险,因为整数溢出会导致我们分配的块比我们意识到的要小得多。
我们已经有了unsigned_add_overflows()
,但让我们补充
unsigned_mult_overflows()
一下
/*
* Returns true if the multiplication of "a" and "b" will
* overflow. The types of "a" and "b" must match and must be unsigned.
* Note that this macro evaluates "a" twice!
*/
#define unsigned_mult_overflows(a, b) \
((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
使用maximum_unsigned_value_of_type
: 检测无符号溢出的助手 (来自提交 1368f6)
该成语(a + b < a)
可以很好地检测无符号整数是否溢出,但更明确
unsigned_add_overflows(a, b)
可能更容易阅读。
定义这样一个宏,大致扩展为((a) < UINT_MAX - (b))
.
因为展开式只在表达式之外使用每个参数一次sizeof()
,所以与具有副作用的参数一起使用是安全的。
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
#define maximum_unsigned_value_of_type(a) \
(UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a)))
是 char中CHAR_BIT
的位数(取决于架构)
您可以查看 Git 2.23(2019 年第三季度)的示例
请参阅René Scharfe ( ) 的提交 921d49b和提交 177fbab(2019 年 6 月 15 日)。(由Junio C Hamano 合并 -- --在提交 e8d2590中,2019 年 7 月 9 日)rscharfe
gitster
用于COPY_ARRAY
复制数组
将调用转换memcpy(3)
为使用COPY_ARRAY
,这会稍微缩短和简化代码。