0

can someone tell me how to use realloc to properly extend calloc?

my expectation: all 20slots to have value of 0.

Outcome: only calloc slots have value of 0, the one I allocate with realloc have random number. output picture

#include <stdio.h>
#include <stdlib.h>
int main(){
    int *ptr;
    int i;
    int n =10;
    ptr = (int*)calloc(n, sizeof(int));    //first time allocate with calloc
    ptr = (int*)realloc(ptr,2*n*sizeof(int));  //extend with realloc
    
    for(i=0;i<2*n;i++){
        printf("ptr[%d]: %d \n", i, ptr[i]);
    }
    return 0;
}

NOTE: before anyone ask why don't I just use calloc(20,sizeof(int));. This is not the real program that I am writing, this is just a short demo so people can see my problem easier. I actually intent to extend calloc much later in the program.

My attempt to find the answer before creating this question. I had google this:

  • How to realloc properly?
  • How to extend Calloc?
  • How to use realloc with calloc?
  • calloc() and realloc() compiling issue
  • several similar to the above.

But I seem to can't find the real answer to this(I might missed it, I'm really sorry). Most of the answer that I got is that they use realloc to extend calloc just like I did, but that is exactly my problem. sorry for bad English.

Clock
  • 3
  • 2
  • 3
    There's no tracking of "slots". `realloc` behaves like `malloc`, the memory isn't initialized. If you need cleared memory, use `memset`. – Thomas Jager Mar 24 '22 at 18:16
  • also make sure you use a temp pointer with `realloc` to [use it properly](https://stackoverflow.com/questions/21006707/proper-usage-of-realloc) – yano Mar 24 '22 at 18:22
  • @ThomasJager is there a way I can realloc to extend calloc yet initialized like calloc at the same time? or should I initialized it to 0 with memset? or just use loop to initialize it individually? – Clock Mar 24 '22 at 18:23
  • 1
    You're looking for a non-existent function called `recalloc` that sets any newly allocated space to zero. It would make sense for it to exist. But it doesn't. – Persixty Mar 24 '22 at 18:25
  • You could, of course, write your own wrapper function which calls calloc, copies the old data into it, and sets the remaining space to zeroes. It would probably run about as fast as an official library function would. The fact that something simple isn't in the libraries doesn't mean it's a bad idea, just that it hasn't been needed frequently enough that making it part of the standard has seemed worthwhile and (usually) that you can build it yourself easily enough. – keshlam Mar 24 '22 at 19:22

1 Answers1

1

The C standard does not provide any routine that performs a reallocation and zeros the additional memory. To achieve this, you can implement it yourself by using realloc to reallocate memory and clearing with memset:

int *newptr = realloc(ptr, 2 * n * sizeof *newptr);
if (!newptr)
{
    fprintf(stderr, "Error, unable to allocate memory.\n");
    exit(EXIT_FAILURE);
}
ptr = newptr;
memset(ptr + n, 0, n * sizeof *ptr);
n *= 2;

You could of course wrap this into a routine, say one called crealloc, and use that. (Unlike the library functions for memory management, it would have to be passed the size of the prior allocation, since code you write does not ordinarily have access to the memory management data structures that provide that size.)

ikegami
  • 367,544
  • 15
  • 269
  • 518
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • @ikegami: There is no `size` in OP’s code; that was a typo in my answer; it should have been `n`. Since they are doubling the size, `n` is both the old size and the amount (of `int`) being added, so the code in this answer is hard-coded for that. It could be generalized so different values for those. – Eric Postpischil Mar 24 '22 at 18:45
  • Maybe also `free` in the event of reallocation failure before exiting? – alex01011 Mar 24 '22 at 18:46
  • @alex01011: [What would be gained from that?](https://stackoverflow.com/search?q=%5Bc%5D+free+exit) Even if you free the memory `ptr` points to, you have not freed all the other memory the program may be using. It is the job of the `exit` routine, any registered `exit` handlers, and the operating system to do any desired cleanup. The major purpose of free is to make memory available for reuse, but there will be no more reuse in a program that is exiting, and the operating system will reclaim the memory for other use. – Eric Postpischil Mar 24 '22 at 18:53
  • @EricPostpischil I see your point, and you are probably right in this case, but what if you were to run a static analysis tool (like valgrind) or a sanitizer and your code is slightly more advanced? Wouldn't you benefit by using `free`? Maybe even trace a bug that wasn't that clear (say an uninitialized pointer). – alex01011 Mar 24 '22 at 19:02
  • @ikegami: The code this is replacing did not update `n` either, and, if it is going to become a `crealloc` routine, that also would not. It is up to the caller of `realloc` to update their record of the size. – Eric Postpischil Mar 24 '22 at 19:06
  • If that's the route you're going to take, then there's no point in doing `ptr = newptr;` either. I also don't think `crealloc` should call `exit` – ikegami Mar 24 '22 at 19:13