Should I force a realloc check if the size of the new block is less than the initial?

Can realloc crash in this case?

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

}

The output in my case is:

 1.ptr: 4072560 2.ptr: 4072560 

So, 'a' points to the same address. So should I provide realloc validation?

Edit later :

  • Using the MinGW Compiler in Windows XP.
  • Is the behavior similar to gcc on Linux?

Then edit 2: Is it possible to check this method?

 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; 
+7
c realloc
source share
6 answers

Yes, you should always check for realloc or any other memory allocation.

The current reuse behavior of the same address is an implementation detail that should not be relied upon. It just opens itself up for errors when either the library switches its implementation or you switch to a new platform.

Could it ever fail? Probably not, I would be amazed if I could find a case that he makes. However, this does not mean that this will not happen. The realloc wrapper in a function that automatically performs a check for each operation is simple enough that there is no reason not to.

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

It would be surprising if realloc when transferring a size smaller than the original distribution, but nothing in the C standard (7.20.3.4) guarantees that it will always be successful:

The realloc function frees the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size . the contents of the new object should be the same as the old object before release, to less than the new and old sizes. Any bytes in the new object beyond the size of the old object are undefined.

If ptr is a null pointer, the realloc function behaves like a malloc function for the specified size. Otherwise, if ptr does not match the pointer previously returned by calloc , malloc or realloc , or if space was freed by calling the free or realloc function, the behavior is undefined. If the memory for a new object cannot be allocated, the old object is not freed and its value is unchanged.

Returns

The realloc function returns a pointer to a new object (which may have the same value as a pointer to an old object) or a null pointer if the new object cannot be selected.

A very simple relevant realloc implementation would be as follows:

 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; } 

In low memory conditions (or any conditions under which malloc will return NULL ), this will return NULL .

It would also be a very simple optimization to return the same pointer if the size of the original distribution is greater than or equal to the requested size. But nothing in the C standard dictates this.

+5
source share

In any case, it is recommended to check the realloc return value (the specification does not say that you are safer if you are shrinking your memory block than if you were expanding it). But you must be careful not to lose the initial pointer (which you do, in your case), since then you will not be able to completely free it.

+2
source share

C99 Standard §7.20.3.4 (realloc) states:

The realloc function frees the old object pointed to by ptr and returns a pointer to a new object, the size of which is given by size. The content of the new object should be the same as that of the old object until liberation, down to the smaller new and old sizes. Any bytes of the new object beyond the size of the old object are undefined.

If ptr is a null pointer, the realloc function behaves like a malloc function for the specified size. Otherwise, if ptr does not match the pointer previously returned by calloc, malloc, or realloc, or if space was freed by a call to the free or realloc function, the behavior is undefined. If the memory for a new object cannot be allocated, the old object is not freed and its value does not change.

Returns

The realloc function returns a pointer to a new object (which may have the same value as a pointer to an old object) or a null pointer if the new object cannot be selected.

Note that the old object is freed; the new object may be in the same place as the old one. And there may be problems. This is unlikely, but it’s much easier to go with the “always” rule than to have strange exceptions.

The normal argument argument is "if this cannot fail, it means that I have a path to the error that I cannot verify." To the point, this is true. However, it may happen that some porting of the memory so that the allocation cannot be successful because the management information is corrupted. Most likely you will just get a core dump, but the code may be strong enough to avoid this. (I assume that the hard-coded 100 and 50 are designed to ask the question: the real-life code will not be over-allocated when it knows how much it really needs.)

If the two calls to "realloc ()" are adjacent, as here, there is very little room for anything to go wrong. However, the working real-life code will have some operations between them - and this code may cause the second realloc () to fail.

Regarding your Change 2 ...

The code could be better written as:

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

But the basic concept is fine. Note that the standard explicitly states that the original selection is safe if a new one cannot be created.

+1
source share

The time it takes to check is so small compared to the time spent in realloc () that I cannot even understand why this would be a problem. Or do you want to reduce the number of lines of code?

+1
source share

realloc() can easily return NULL when downsizing.

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

realloc(any_pointer, 0) may return NULL or maybe some not-NULL pointer, this implementation is defined.

This is why realloc()/malloc() failure should not be a simple if (ptr == NULL) test, but

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

Because of this ambiguity, the code should make the realloc() wrapper, recommend something like:

 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 } 

Getting NULL in realloc() with a reduced size, therefore, is not a failure, and therefore this answer only tangentially, but the OP question: "... force realloc if the new block size is less than the initial?" and then used the less reliable if (ptr == NULL) paradigm.

0
source share

All Articles