问题
There is no reason for realloc()
ing to a smaller size will fail. It's freeing up the remainder. I see no reason at all for it to fail. This being said, is it safe to assume that realloc()
ing to a smaller size will never fail?
回答1:
TL;DR
No, you cannot assume that.
There is no reason for realloc()ing to a smaller size will fail. It's freeing up the remainder. I see no reason at all for it to fail.
chux covered details about this pretty well. So I answer in a more general way.
The type of reasoning you're using here is a quite dangerous one. Your basic reasoning is "I cannot see why X is true, therefore I assume X is false." Be very careful with reasoning that way.
First, let's skip the very obvious danger that even though you cannot see any reason for realloc
failing in this case, that does not mean that you are correct.
Instead let's assume that you are correct. That there is provably no rational reason whatsoever to implement realloc
in such a way that it would ever fail is the new size is equal or smaller than the original. Then it's still a faulty argument, because you cannot assume that the programmers who coded the implementation you're using had this knowledge. There was a provably optimal way of doing this, but the coders did not know that.
Also, the very fact that the C standard does NOT say that this is safe is a good indication (however, not a proof) that there are good reasons to not give that guarantee.
If the specifications does not say that it always succeeds during some circumstances, then you should always consider the risk of failure as non-zero. And in this case, the standard does not give any promises, so no you cannot assume that.
Also, in reality there is often the case where it would be relatively easy to implement things in a "good" way, but it will still be more complicated than the simplest way. And sometimes that simplicity is desirable. The easiest way I can think of to implement realloc
is something like this:
void *realloc(void *ptr, size_t new_size)
{
void *ret = malloc(new_size);
if(ret) {
memcpy(ret, ptr, new_size);
free(ptr);
}
return ret;
}
One very valid reason of implementing it this way would be that you have a specific environment where you typically never would use realloc
and you throw this in for the sole purpose of conforming to the standard. And whenever you do something for the sole purpose of conforming to a standard or specification, you would typically go for simplicity above all else.
回答2:
"There is no reason for realloc()ing to a smaller size will fail." is an assertion without evidence.
As the spec for the Standard C library does not require a reduction to never fail, robust code would not assume an error is not possible, even if unlikely.
In particular, C17dr spec has Future library directions which discusses reduction to 0.
Invoking
realloc
with a size argument equal to zero is an obsolescent feature.
I take this to imply now and in the future, the following code which reduces the allocation to 0 should be avoided.
void *p = malloc(42);
...
realloc(p, 0); // Obsolete
// and instead
free(p);
回答3:
From the linux manpages:
The realloc() function returns a pointer to the newly allocated memory, which is suitably aligned for any built-in type and may be different from ptr. [...] If
realloc()
fails, the original block is left untouched; it is not freed or moved.
It cannot be assumed that the block will not be moved because this is implementation-specific. For example, the block could be moved in the case of compactification.
回答4:
For cases where the requested size is smaller than the original and non-zero, one could safely make a copy of the original pointer before calling realloc
, and set the pointer back to that value in case the realloc returns null. If the realloc size is zero, things are a bit murky. Some implementations would treat realloc(ptr, 0);
as equivalent to free(ptr); return 0;
, which would return null after freeing the object, but others would treat it as equivalent to realloc(ptr,1);
, which would only return null in cases where the original pointer would still be valid. Unfortunately, there's no general way of knowing which behavior an implementation would use, and thus no way to properly handle a null return from realloc(ptr, 0);
.
回答5:
There is no reason for realloc()ing to a smaller size will fail.
Consider an implementation that grabs large blocks from the platform's underlying address space allocator and dices them into small pieces. A realloc
that reduces the size of the allocation might require a new block to be allocated if the size requested is not within the range of supported sizes for the large block the block being reallocated came from.
In this case, the implementation will need to get a smaller block from a sub-allocator whose range of serviced sizes includes the size requested. That sub-allocator may not have any free blocks and when it requests a new large block to dice up, that can fail.
So the premise of this question is false.
Also, in general, it is a terrible idea to leap from "I cannot think of any reason this would fail" to "I can assume this will not fail". There are many stories of things that failed for reasons people could not foresee and some of them have horrible consequences.
来源:https://stackoverflow.com/questions/62784807/is-it-safe-to-assume-that-reallocing-to-a-smaller-size-will-always-succeed