c/c++语言开发共享如果新块大小小于初始块,我应该强制执行realloc检查吗?

在这种情况下realloc会失败吗?

int *a = NULL; a = calloc(100, sizeof(*a)); printf("1.ptr: %dn", a); a = realloc(a, 50 * sizeof(*a)); printf("2.ptr: %dn", a); if(a == NULL){ printf("Is it possible?n"); } return (0); 

}

我的输出是:

 1.ptr: 4072560 2.ptr: 4072560 

所以’a’指向相同的地址。 那么我应该强制执行realloc检查吗?

稍后编辑

稍后编辑 2:检查这种方式可以吗?

 int *a = NULL, *b = NULL; a = calloc(100, sizeof(*a)); b = realloc(a, 50 * sizeof(*a)); if(b == NULL){ return a; } a = b; return a; 

    是的,您应该始终对realloc或任何其他内存分配强制执行检查。

    重用相同地址的当前行为是不应依赖的实现细节。 这样做只是在库切换它的实现或移动到新平台时打开自己的bug。

    这可能会失败吗? 可能不会,如果你能找到一个案例,我会感到震惊。 然而,这并不意味着它不会。 在一个自动检查每个操作的函数中包装realloc非常简单,没有理由不这样做。

     void* xrealloc(void* ptr, size_t size) { ptr = realloc(ptr, size); if ( !ptr ) { exit(EXIT_FAILURE); } return ptr; } 

    如果realloc在传递小于原始分配的大小时失败,那将是令人惊讶的,但C标准(7.20.3.4)中没有任何内容保证它将始终成功:

    realloc函数解除分配ptr指向的旧对象,并返回指向具有size指定size的新对象的指针。 新对象的内容应与解除分配之前的旧对象的内容相同,直到新旧大小中的较小者为止。 新对象中超出旧对象大小的任何字节都具有不确定的值。

    如果ptr是空指针,则realloc函数的行为类似于指定大小的malloc函数。 否则,如果ptr与之前由callocmallocrealloc函数返回的指针不匹配,或者如果通过调用freerealloc函数释放了空间,则行为未定义。 如果无法分配新对象的内存,则不会释放旧对象,并且其值不会更改。

    返回

    realloc函数返回指向新对象的指针(可能与指向旧对象的指针具有相同的值),如果无法分配新对象,则返回空指针。

    realloc一个非常简单的符合实现是:

     void *realloc(void *ptr, size_t size) { void *new_ptr= malloc(size); if (new_ptr && ptr) { size_t original_size= _get_malloc_original_size(ptr); memcpy(new_ptr, ptr, min(original_size, size)); free(ptr); } return new_ptr; } 

    在低内存条件下(或malloc将返回NULL任何条件),这将返回NULL

    如果原始分配的大小大于或等于请求的大小,则返回相同的指针也是一种非常简单的优化。 但是C标准中的任何内容都没有规定。

    在任何情况下检查realloc的返回值是一个好习惯(规范并不表示如果缩小内存块比放大内存块更安全)。 但是你应该注意不要丢失初始指针(在你的情况下你做的),因为你完全无法释放它。

    C99标准§7.20.3.4(realloc)说:

    realloc函数解除分配ptr指向的旧对象,并返回指向具有size指定大小的新对象的指针。 新对象的内容应与解除分配之前的旧对象的内容相同,直到新旧大小中的较小者为止。 新对象中超出旧对象大小的任何字节都具有不确定的值。

    如果ptr是空指针,则realloc函数的行为类似于指定大小的malloc函数。 否则,如果ptr与之前由calloc,malloc或realloc函数返回的指针不匹配,或者如果通过调用free或realloc函数释放了空间,则行为未定义。 如果无法分配新对象的内存,则不会释放旧对象,并且其值不会更改。

    返回

    realloc函数返回指向新对象的指针(可能与指向旧对象的指针具有相同的值),如果无法分配新对象,则返回空指针。

    请注意,旧对象已取消分配; 新对象可能恰好指向与旧对象相同的位置。 可能会有问题。 这是不太可能的,但是使用规则“总是”而不是有奇怪的例外要简单得多。

    正常的反驳论据是“如果这不能失败,那就意味着我有一个我无法测试的错误路径”。 到目前为止,这是事实。 但是,可能存在一些内存的踩踏,因此分配不能成功 – 因为控制信息已被破坏。 更有可能你只是获得核心转储,但也许代码足够强大,能够避免这种情况。 (我假设硬编码的100和50是为了提出问题的目的;现实生活代码在知道它真正需要多少时不会过度分配。)

    两个调用’realloc()’的地方相邻,就像这里一样,没有什么可以出错的空间。 但是,实际工作代码会在两者之间进行一些操作 – 而且该代码可能导致第二个’realloc()’失败。

    关于你的’编辑2’……

    代码可能更好地编写为:

     if (b != NULL) a = b; return a; 

    但基本概念还可以。 请注意,标准明确指出,如果无法创建新分配,则原始分配是安全的。

    与在realloc()中花费的时间相比,进行检查所花费的时间非常少,我甚至无法理解为什么它会成为一个问题。 或者你想减少代码行数?

    realloc()可以在减小尺寸时轻松返回NULL

     void *ptr = malloc(10); ptr = realloc(ptr, 0); if (ptr == NULL) { puts("Failure because return value is NULL? - not really"); } 

    realloc(any_pointer, 0)可能返回NULL或者某些not-NULL指针,它是实现定义的。

    这就是为什么realloc()/malloc()失败不应该是if (ptr == NULL)的简单测试。

     void *ptr = malloc(newsize); // or realloc(..., newsize) if (ptr == NULL && newsize > 0) { exit(0); // Handle OOM; } 

    由于这种歧义,如果代码想要创建一个realloc()包装器,建议如下:

     void *xrealloc(void *ptr, size_t newsize, bool *falure) { *failure = 0; if (newsize > 0) { void *tmp = realloc(ptr, newsize); if (tmp == NULL) { *failure = 1; return ptr; // old value } return tmp; // new value } free(ptr); return NULL; // new value } 

    因此在减小大小的realloc()上获取NULL并不是真正的失败 ,所以这个答案只是切线应用,但OP的问题是“…强制重新分配检查新块大小是否小于初始值?” 然后使用不太值得信赖的if (ptr == NULL)范例。

      以上就是c/c++开发分享如果新块大小小于初始块,我应该强制执行realloc检查吗?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/560818.html

      (0)
      上一篇 2021年1月28日
      下一篇 2021年1月28日

      精彩推荐