如何避免realloc溢出?

时间:2017-04-03 11:40:36

标签: c memory-management malloc realloc calloc

可以使用OpenCV Error: The function/feature is not implemented () in CvStatModel::write, file ..\..\..\modules\ml\src\inner_functions.cpp安全地在C中分配大小为x的{​​{1}}元素,而y会处理乘法calloc(x, y)

但是calloc()例如只将新大小作为参数,我想知道如何使用x*y安全地重新分配realloc()个字节。

如果x*y不适合realloc(),该怎么办? x*y如何处理这个问题?

5 个答案:

答案 0 :(得分:4)

size_t是无符号类型,size_t的最大值是可以使用reallocmalloc分配的对象的绝对最大大小;这可以在宏SIZE_MAX中找到。在32位个人计算机上,size_t通常是32位; 64位计算机上的64位。这应该足够了。

为确保item_size * n_items的计算不会溢出,您可以将SIZE_MAX除以item_size并确保结果值大于或等于n_items

size_t max_items = SIZE_MAX / item_size;
if (max_items < n_items) {
    // an overflow would occur
}
else {
    // it is ok
}
如果分配失败,

calloc必须返回NULL,因此calloc最有可能检查类似于上面的那个。

答案 1 :(得分:1)

简短的回答是你无法安全地做到这一点。您可以做的最多是限制尝试分配的内存量,使其不超过SIZE_MAX

SIZE_MAXsizeof运算符可以生成的最大值。

C中的每种数据类型都必须具有可以使用sizeof计算的大小,包括数组,以及使用malloc()calloc()或{{1}分配的任何连续内存块}}

如果realloc()在数学上大于x*y,那么无法以任何方式分配该数量的内存。即使底层系统支持,C程序也无法完全使用该内存块。

还有一个问题是,计算SIZE_MAX(假设x*yx的类型为y)将使用模运算,因此实际上会给结果在数学上等效到size_t

答案 2 :(得分:1)

  

如果x * y不适合size_t怎么办? calloc()如何处理这个问题?

realloc()malloc()受到限制,因为传递给它们的size参数仅限于SIZE_MAXcalloc()

不是这样

符合要求的C实现要求calloc()限制仅分配SIZE_MAX的内存。以下可能有效。单个类型的最大大小为SIZE_MAX数组大小可以与SIZE_MAX SIZE_MAX-1 “bytes”一样大,但下面的iptr不是数组,而是指针。

// Assume sizeof(double) == 8
double *iptr = calloc(SIZE_MAX, sizeof *iptr);

重新分配如此大的指针是有问题的,因为它需要使用另一个调用calloc()

  

如何避免realloc溢出?

OP的问题不在于realloc()可以处理的问题,而在于代码如何计算传递给它的值可能会溢出。

确保无符号类型(如size_t)不会溢出乘法:

  if (b && a > SIZE_MAX/b) Handle_Overflow();
  prod = a*b;

答案 3 :(得分:0)

size_t是无符号类型。

对于无符号类型,溢出行为是确定性的,如C11

中所述
  

[....]因为无法用结果无符号整数类型表示的结果是   减少模数可以是最大值的数字   由结果类型表示。

因此,只要确保生成要存储在变量类型size_t中的值的操作在进程中没有溢出,将该变量传递给realloc()就不会产生任何影响。最多,realloc()将无法分配该内存。

答案 4 :(得分:0)

如果x * y溢出size_t,realloc将尝试分配溢出的值:

bytes = (x * y) % 2^(sizeof(size_t) * 8)

因此realloc将“看到”bytes个字节数。它没有照顾任何事情。