Heap Buffer Overflow trying to reallocate memory. C Language - c

I've been writing codes for Min Stack on LeetCode.
Problem I'm having is when I try to reallocate memory(on push method), it tells me "Address Sanitizer: Heap Buffer Overflow."
What's causing this and how can I fix the issue? Thank you
Also, what would be a better way to solve this problem?
typedef struct {
int top;
int *arr;
int min;
int size;
} MinStack;
/** initialize your data structure here. */
MinStack* minStackCreate() {
MinStack* stack = (MinStack*)malloc(sizeof(MinStack));
stack->size = 10;
stack->top = -1;
stack->min = INT_MAX;
stack->arr = (int*) malloc(sizeof(int)*(stack->size));
return stack;
}
void minStackPush(MinStack* obj, int x) {
//if top+1 is equal to the size of the stack(when stack is full),
//I want to multiply the size by 2
//so more numbers can fit in the stack.
if(obj->top+1 == obj->size){
obj->size = obj->size*2; // this line seems to give me issues.
obj->arr = realloc(obj->arr, obj->size);
}
obj->arr[obj->top+1] = x;
obj->top++;
}

The problem seems to be coming from your realloc call, according to the man page:
The realloc() function changes the size of the memory block pointed to by ptr to size bytes.
So you need to have obj->arr = realloc(obj->arr, sizeof(int) * obj->size);
Otherwise your indexing will be off.
It also seems that you're calling realloc on every call, rather than only when you need to increase the size of your array, I'd advise moving that call to inside your if(obj->top+1 == obj->size) statement.

Insufficient/incorrect allocation. realloc() needs the byte count, not just the element count.
// obj->arr = realloc(obj->arr, obj->size);
obj->arr = realloc(obj->arr, sizeof *(obj->arr) * obj->size);
Aside: Robust code would check the realloc() result before assigning to obj->arr. #Eugene Sh.

Related

Why is my program not reallocating memory in C?

I'm working on this program that creates a stack, pushes and pops values then deletes the stack and deallocates the memory. What I want the function stack_push to do is push values to the stack and if the stack is full, it doubles the amount of memory it has, basically reallocating the memory and doubling it. In this case, it should go from 5 variables to 10. Yet for some reason, it's not doing that. I believe the error stems from my attempt at reallocating memory, what am I doing wrong and how would I go about fixing it?
typedef struct stack
{
int capacity;
int size;
double *data;
} Stack;
Stack *ptr;
Stack *stack_create(void){
ptr = (Stack*)malloc(sizeof(Stack));
ptr->capacity = 5;
ptr->size = -1;
ptr->data = (double*)malloc(sizeof(double) * ptr->capacity);
return ptr;
}
void stack_push(Stack *s, double value){
if (s->size >= s->capacity-1){
ptr = (Stack *)realloc(ptr, 2*sizeof(Stack));
};
ptr->data[++ptr->size] = value;
}
int main(void)
{
// Create an empty stack.
Stack *s = stack_create();
for (int i = 0; i < 10; i++) {
stack_push(s, i);
}
return 0;
}
You're reallocating an additional stack, not more elements in the stack:
ptr = (Stack *)realloc(ptr, 2*sizeof(Stack));
What you want instead is:
ptr->data = realloc(ptr->data, 2 * ptr->capacity * sizeof(double));
if (!ptr->data) {
perror("malloc failed");
exit(1);
}
ptr->capacity *= 2;
The last line keeps track of the updated capacity so that you'll know when you need to reallocate again.
Note that you should always check the return value of malloc and realloc to ensure that the memory was successfully allocated, and that you shouldn't cast the return value as that can mask other errors in your code.
This post highlights the dangers of not reading manuals, FAQs and textbooks when learning. I suggest picking up a copy of K&R2e and doing the exercises as you stumble across them.
ptr = (Stack *)realloc(ptr, 2*sizeof(Stack));
For a start, you're working in C, not C++; you shouldn't be casting the return value of realloc. That's probably not going to cause any headaches beyond what you'd expect from boilerplate crud, but what will cause headaches is if you don't realise the value of ptr may change, and that change will only be local to stack_push because of pass-by-value semantics. Additionally, when ptr does change (but not for the caller), realloc has invalidated the old value, which leads the caller somewhere into this line of frequently asked questions...
See what I mean? Just from this one line of code I can see that your textbooks, college classes and whatnot aren't working out well. Something needs to change. Please 🙏 do consider reading K&R2e and doing those exercises when you can.

stack implementation using malloc in c [BEGINNER]

for learning purpose I'm implementing a stack with it's functions in c.
I added some small additional functionality to use malloc the first time and try to understand it properly.
I wrote a function which is initially creating my stack struct. The return value of the function is a new struct with an already allocate memory. What is the best way to handle a malloc exception in a function which return value should be a struct? Maybe should I design the function different? I'm aware that the printf is not doing it's job ;)
My Stack struct:
typedef struct Stack
{
int count;
int capacity;
int *data;
} Stack;
Creating a Stack instance:
Stack create_stack(int initialcapacity)
{
Stack new_stack;
new_stack.count = 0;
new_stack.capacity = initialcapacity;
if (!(new_stack.data = malloc(initialcapacity * sizeof(int))))
printf("not enough memory!");
return new_stack;
}
The function is called with the initial capacity of the stack:
Stack stack = create_stack(10);
A second question came up while I was writing a function to delete the Stack instance.
int delete_stack(Stack *stack)
{
stack->count = 0;
stack->capacity = 0;
free(stack->data);
stack->data = NULL;
return 0;
}
Am I able to remove also the struct instance itself? It feels not complete to just set the values back to 0 and direct int* to NULL.
Last but not least, I have a question to my push function. Also here I added some functionality which allows me to push something on the stack while it is already full:
void push(int value, Stack *stack)
{
if (stack->count == stack->capacity)
{
int *temp = malloc(stack->capacity * sizeof(int));
int i;
for (i = 0; i < stack->count; i++)
temp[i] = stack->data[i];
free(stack->data);
stack->data = NULL;
stack->data = malloc(stack->capacity * 2 * sizeof(int));
for (i; i > -1; i--)
stack->data[i] = temp[i];
free(temp);
temp = NULL;
stack->data[stack->count] = value;
stack->count++;
stack->capacity = stack->capacity * 2;
}
else
{
stack->data[stack->count] = value;
stack->count++;
}
}
Is it necessary to "free" the smaller array and put the pointer to NULL before I allocate a new array double the size?
If there is anything from my code which is unnecessary or not written properly, please let me know, I'm grateful for any hint which makes me better.
Cheeers,
me
I would do it with pointers. That is, your create_stack() would allocate a new Stack struct using malloc, then set the values to the struct and usee malloc again to allocate space for the Stack->data. Like this:
Stack* create_stack(int initialcapacity) {
Stack* new_stack = malloc(sizeof(Stack));
if (new_stack == NULL)
return NULL; // return null to tell the caller that we failed
new_stack->count = 0;
new_stack->capacity = initialcapacity;
new_stack->data = malloc(initialcapacity * sizeof(int))
if (new_stack->data == NULL)
{
free(new_stack);
return NULL;
}
return new_stack;
}
With this, we "handle" a malloc error by returning NULL, so the caller knows we failed.
Now that we have used malloc to allocate the Stack struct, you can (read: MUST) free the space taken by it using free(stack); in delete_stack().
In push(), the temporary array is not needed, that is, you could just right away allocate a bigger array, copy the contents to it from the original stack->data, free stack->data and set it to the newly malloc'd array:
int *temp = malloc(stack->capacity * 2 * sizeof(int));
// TODO: what if malloc fails?
int i;
for (i = 0; i < stack->count; i++)
temp[i] = stack->data[i];
free(stack->data);
stack->data = temp;
stack->data[stack->count] = value;
stack->count++;
stack->capacity = stack->capacity * 2;
Q. What is the best way to handle a malloc exception in a function which return value should be a struct?
There are at least three ways:
1) Instead of returning structure itself, return a pointer to it. This means two mallocs: one is for structure itself and another one is for data field. Returning NULL pointer means that something went wrong during construction.
struct Stack* create_stack(int initialcapacity) {
struct Stack* stack = malloc(sizeof(struct Stack));
...
return stack;
}
2) More flexible way is to pass pointer to already allocated structure. Flexibility comes from idea that calling code controls where to allocate structure: on stack or in dynamic memory. Return value of function may be used solely to notify calling code about errors:
bool create_stack(int initialcapacity, struct Stack* stack) {
...
}
// if calling code wants structure on stack (yeah, "stack" on stack)
struct Stack stack;
if (!create_stack(50, &stack)) {
die();
}
// if calling code wants it in dynamic memory
struct Stack* stack = malloc(sizeof(struct Stack));
if (!stack) {
die();
}
if (!create_stack(50, stack)) {
die();
}
3) If your program is not a 10,000+ LOC production code, easiest way may be to simply print error message and abort program immediately if allocation fails. Usually allocation errors are fatal: you can't recover in any meaningful way if there is not enough memory. You may even create a wrapper function over malloc to automatically catch such errors and exit:
void* my_malloc(size_t count) {
void* ptr = malloc(count);
if (ptr == NULL) {
fprintf(stderr, "Allocation failed");
exit(EXIT_FAILURE);
}
return ptr;
}
Q. Am I able to remove also the struct instance itself?
No, you can't. Because it is allocated on stack (the structure itself, not the data). If you want to delete structure itself, you need to use approach #1 from above.
And, by the way, there is no need to set zeroes and NULLs to fields. It doesn't delete anything. Such approach is used rarely and with only purpose to catch bugs (when calling code first deletes some structure and then tries to use it afterwards).
Q. Is it necessary to "free" the smaller array and put the pointer to NULL before I allocate a new array double the size?
Once again, you don't need to NULLify anything -- it doesn't delete anything. Instead of two mallocs and manual copying use realloc, which will do most of the work for you.
Generally, you should be able to declare a structure, then have an array of say 64 of them, with an integer to say which entry is on the top. Very simple, and no dynamic allocation. But 64 is pretty low, That's because stacks, recursion, and levels of nesting are intimately linked. Usually it should be possible to see that 64 is an insane level of nesting, and no legitimate input will ever even approach it. You then might need a guard to protect from malicious or corrupted input, but that just terminates the program or sub-routine.
If you can't establish a low sanity bound on a stack, it might that you still need one. Either it's a rare case where nesting goes very deep, or it's that you haven't approached the problem in the best way, but a sub-optimal program that still works is better than no program.
So you use the same structure, but the stack is set up with a call to
malloc() and, if it grows out of bounds, regrow with a call to realloc().
You might want to still sanity check it, but now sanity checks are
much higher, a million or so as opposed to 64. You also have to check that
realloc does not fail.
typedef struct
{
int x;
char astring[32];
} ENTRY;
static ENTRY *stack = 0;;
static int top = -1;
static int N = 0;
void push(const ENTRY *e)
{
/* grow logic like this */
ENTRY *temp = realloc(stack, newsize * sizeof(ENTRY));
if(temp)
stack = temp;
else
{
/* reallocation has failed but stack still valid */
free(stack);
N = 0;
top = -1;
/* for the sake of argument do this. We need temp to avoid
a memory leak */
fprintf(stderr, "out of memory\n");
}
/* push here, trivial */
}
int pop(ENTRY *e)
{
/* e is a non-const pointer. Fill and reset stack top */
}
You might want the stack global as in the example or you might want to
wrap it in a structure you pass about. Usually you'll want either pointers
or structures on the stack, but occasionally you might need a stack
of integers or floating point values.
There's no good way of handling memory allocation errors in C, especially
ones which can't happen (a computer with several GB of memory installed
is more likely to develop an electrical fault than to run out
of memory when asked for a couple of kilobytes). The usual rule is to
shunt up. But that makes the push call difficult, because every push
could potentially run the computer out of memory (but it can't really,
it's just your encapsulation allows the function to fail).

Realloc an array but do not lose the elements in it

Code:
int * data;
data = malloc(sizeof(int)*10);
int i;
for(i=0;i<10;i++)
data[i]=i;
int * aux;
aux = realloc(data,sizeof(int)*20);
if(aux)
data=aux;
for(i=10;i<20;i++)
data[i]=i;
A teacher once told me "No, you can't reallocate an array with elements without a backup"; I said, "Oh, OK", but now that make no sense to me.
The memory pointed by the pointer is already allocated so is "impossible" to lose it; if I make a safe realloc there should be no problem.
My question is: if I want to resize an dynamic array, is the above example code valid?
Your code is not entirely valid. Here's a partly annotated modified version:
size_t size = 10; // Keep a record of the size of the array
int *data = malloc(sizeof(*data) * size);
if (data != 0) // Always check that the allocation succeeds
{
for (size_t i = 0; i < size; i++)
data[i] = i;
size_t new_size = size * 2; // Grow arrays by doubling as a general rule
int *aux = realloc(data, sizeof(*aux) * new_size);
if (aux != 0) // Test allocation - as you did anyway
{
data = aux;
// Only initialize new data if successful
for (size_t i = size; i < new_size; i++)
data[i] = i;
size = new_size; // Record new size of array
}
}
/* At this point, if data != 0, it is safe to access data[0]..data[size-1] */
You need to know how big the array is at the end of this fragment. In this version, if data is not null, then size records its size. (If data is null, you should probably be bailing out by now.) In your original code, you didn't know what size the array was. This was a major problem; you cannot use the array safely if you don't know how big it is.
The allocations use sizeof(*data) so that if the type of data changes (say to double *data), the rest of the malloc() statement does not have to change. That's an advantage of not casting the result of malloc() or realloc().
It is OK. Just two three more things to make it perfect,
Check for malloc() success before using the returned pointer.
If realloc() fails, you should not be accessing the array with new dimension.
After this code block, it's difficult to find out whether the allocated memory for data has been changed (20) or not (10). So, the better approach is to instead of checking for not-NULL,
check for NULL as the returned pointer of realloc()
stop/return/abort if it's NULL [ or use the old dimension for further code, if you may]
continue with the new dimension otherwise.
It's mostly ok. The final two lines of code, where you init the new values, need to be inside the if-statement in case the reallocation failed. Otherwise you're accessing your original buffer, which was only allocated for 10 elements, so you will end up accessing memory that doesn't belong to you.

Manipulating dynamic array using realloc in a function

Using what I have learned here: How to use realloc in a function in C, I wrote this program.
int data_length; // Keeps track of length of the dynamic array.
int n; // Keeps track of the number of elements in dynamic array.
void add(int x, int data[], int** test)
{
n++;
if (n > data_length)
{
data_length++;
*test = realloc(*test, data_length * sizeof (int));
}
data[n-1] = x;
}
int main(void)
{
int *data = malloc(2 * sizeof *data);
data_length = 2; // Set the initial values.
n = 0;
add(0,data,&data);
add(1,data,&data);
add(2,data,&data);
return 0;
}
The goal of the program is to have a dynamic array data that I can keep adding values to. When I try to add a value to data, if it is full, the length of the array is increased by using realloc.
Question
This program compiles and does not crash when run. However, printing out data[0],data[1],data[2] gives 0,1,0. The number 2 was not added to the array.
Is this due to my wrong use of realloc?
Additional Info
This program will be used later on with a varying number of "add" and possibly a "remove" function. Also, I know realloc should be checked to see if it failed (is NULL) but that has been left out here for simplicity.
I am still learning and experimenting with C. Thanks for your patience.
Your problem is in your utilisation of data, because it points on the old array's address. Then, when your call realloc, this area is freed. So you are trying to access to an invalid address on the next instruction: this leads to an undefined behavior.
Also you don't need to use this data pointer. test is sufficient.
(*test)[n-1] = x;
You don't need to pass data twice to add.
You could code
void add(int x, int** ptr)
{
n++;
int *data = *ptr;
if (n > data_length) {
data_length++;
*ptr = data = realloc(oldata, data_length * sizeof (int));
if (!data)
perror("realloc failed), exit(EXIT_FAILURE);
}
data [n-1] = x;
}
but that is very inefficient, you should call realloc only once in a while. You could for instance have
data_length = 3*data_length/2 + 5;
*ptr = data = realloc(oldata, data_length * sizeof (int));
Let's take a look at the POSIX realloc specification.
The description says:
If the new size of the memory object would require movement of the object, the space for the previous instantiation of the object is freed.
The return value (emphasis added) mentions:
Upon successful completion with a size not equal to 0, realloc() returns a pointer to the (possibly moved) allocated space.
You can check to see if the pointer changes.
int *old;
old = *test;
*test = realloc(*test, data_length * sizeof(int));
if (*test != old)
printf("Pointer changed from %p to %p\n", old, *test);
This possible change can interact badly because your code refers to the "same" memory by two different names, data and *test. If *test changes, data still points to the old chunk of memory.

How to make the bytes of the block be initialized so that they contain all 0s

I am writing the calloc function in a memory management assignment (I am using C). I have one question, I wrote the malloc function and thinking about using it for calloc as it says calloc will take num and size and return a block of memory that is (num * size) which I can use malloc to create, however, it says that I need to initialize all bytes to 0 and I am confused about how to do that in general?
If you need more info please ask me :)
So malloc will return a pointer (Void pointer) to the first of the usable memory and i have to go through the bytes, initialize them to zero, and return the pointer to that front of the usable memory.
I am assuming you can't use memset because it's a homework assignment assignment, and deals with memory management. So, I would just go in a loop and set all bytes to 0. Pseudocode:
for i = 1 to n:
data[i] = 0
Oh, if you're having trouble understanding how to dereference void *, remember you can do:
void *b;
/* now make b point to somewhere useful */
unsigned char *a = b;
When you need to set a block of memory to the same value, use the memset function.
It looks like this: void * memset ( void * ptr, int value, size_t num );
You can find more information about the function at: http://www.cplusplus.com/reference/clibrary/cstring/memset/
If you can't use memset, then you'll need to resort to setting each byte individually.
Since you're calling malloc from your calloc function, I'm going to assume it looks something like this:
void *calloc (size_t count, size_t sz) {
size_t realsz = count * sz;
void *block = malloc (realsz);
if (block != NULL) {
// Zero memory here.
}
return block;
}
and you just need the code for "// Zero memory here.".
Here's what you need to know.
In order to process the block one byte at a time, you need to cast the pointer to a type that references bytes (char would be good). To cast your pointer to (for example) an int pointer, you would use int *block2 = (int*)block;.
Once you have the right type of pointer, you can use that to store the correct data value based on the type. You would do this by storing the desired value in a loop which increments the pointer and decrements the count until the count reaches zero.
Hopefully that's enough to start with without giving away every detail of the solution. If you still have problems, leave a comment and I'll flesh out the answer until you have it correct (since it's homework, I'll be trying to get you to do most of the thinking).
Update: Since an answer's already been accepted, I'll post my full solution. To write a basic calloc in terms of just malloc:
void *calloc (size_t count, size_t sz) {
size_t realsz, i;
char *cblock;
// Get size to allocate (detect size_t overflow as well).
realsz = count * sz;
if (count != 0)
if (realsz / count != sz)
return NULL;
// Allocate the block.
cblock = malloc (realsz);
// Initialize all elements to zero (if allocation worked).
if (cblock != NULL) {
for (i = 0; i < realsz; i++)
cblock[i] = 0;
}
// Return allocated, cleared block.
return cblock;
}
Note that you can work directly with char pointers within the function since they freely convert to and from void pointers.
Hints:
there is already a posix library function for zeroing a block of memory
consider casting the void * to some pointer type that you can dereference / assign to.

Resources