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.
Related
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.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I tried to create my own malloc function in C, using array as the memory i'll be working with. But when the remaining memory size surpasses a certain number of bits, the program crashes saying " Exception thrown: write access violation."
I divide the memory to a blocks. Each block will have a little metadata block that preserves the size of the block and whether is it free or taken (at the beginning, the entire memory array is one big block).
Then my malloc finds the first memory block with sufficient size and uses it (or part of it).
The problem is:
If i initialize an array of size 20000 bytes for example, my malloc will only work if the remaining free bytes in array would be 17708 or more.
#include <stdio.h>
char memory[20000];
struct block {
unsigned int size;
int free;
struct block* next;
};
struct block* freeList = (void*)memory;
void initialize() { /
freeList->size = 20000 - sizeof(struct block);
freeList->free = 1;
freeList->next = NULL;
}
void split(struct block* fitting_slot, unsigned int size) {
struct block* new = (void*)(fitting_slot + size + sizeof(struct block));
unsigned int temp = (fitting_slot->size) - size - sizeof(struct block);
printf("Remaining memory size is %d\n", temp);
new->size = temp; // this is where program crashes
new->free = 1;
new->next = fitting_slot->next;
fitting_slot->size = size;
fitting_slot->free = 0;
fitting_slot->next = new;
}
void* MyMalloc(unsigned int noOfBytes) {
struct block* curr;
void* result;
if (!(freeList->size)) {
initialize();
}
curr = freeList;
while ((((curr->size) < (noOfBytes + sizeof(struct block))) || ((curr->free) == 0)) && (curr->next != NULL)) {
curr = curr->next;
}
printf("From the free memory of size : %d\n", curr->size);
printf("We will occupy this size : %d\n", noOfBytes + sizeof(struct block));
if ((curr->size) == (noOfBytes + sizeof(struct block))) {
curr->free = 0;
result = (void*)(++curr);
printf("Exact fitting block allocated\n\n");
}
else if ((curr->size) > (noOfBytes + sizeof(struct block))) {
split(curr, noOfBytes);
result = (void*)(++curr);
printf("Fitting block allocated with a split\n\n");
}
else {
result = NULL;
printf("Sorry. No sufficient memory to allocate\n\n");
}
return result;
}
int main(){
unsigned int size = 2270 * sizeof(char);
char* k = (char)MyMalloc(size);
printf("Success\n");
}
If the number of "size" is 2269 or lower, program works correctly.
If the number of "size" in main is 2270 or higher, program crashes on the line
new->size = temp in function split() saying "Exception thrown: write access violation."
OK, so I think you are offsetting by the wrong amount. Pointers in C have an indication of the size of thing they are pointing to, so if you want a byte offset you need to cast the pointer to char*, or I think void* should also work fine. (see the edit below, this was mistaken)
I have not done a detailed debug, however changing line 20 from
struct block* new = (void*)(fitting_slot + size + sizeof(struct block));
to:
struct block* new = (void*)(fitting_slot) + size + sizeof(struct block);
seemed to at least stop the errors.
I can set size right up to 19968 (the max) and all seems well.
EDIT
So, as #R.. correctly pointed out below, arithmatic on void pointers is not allowed (although gcc and probably other compilers let you get away with it) - see this answer, for example, on the topic.
The most appropriate thing would seem to be casting to char*. Given that the fitting_slot variable is also already in units of the block size, rather than adding sizeof(struct block) it is simpler to just add 1 to that, then the size once case to char:
struct block* new = (void*)((char*)(fitting_slot+1) + size);
I've tested this and it seems to work the same in gcc as the previous edit, but legally now.
In the line where new is assigned pointer arithmetic is done on a struct block*.
When you do pinter arithmetic on a typed pointer, c semantics assumes, that an array is being manipulated. For example ptr++ on a struct block* increases the value of the pointer by sizeof(struct block).
You should cast your pointer to char* before performing arithmetic on it this way. I am not sure I got everything, but I hope this can get you started.
I used my debugger.I assume that you forgot a malloc in split function.
struct block* new = (void*)malloc(fitting_slot + size + sizeof(struct block));
If you use a debbuger you'll find out that new->size was unreachable address.
**this would be line 20, if the include is in line 1.
so I'm trying to build a stack in C, using pointers and malloc.
My stack.h has a struct
typedef struct
{
int *top;
int *prev;
} intstack_t;
I'm initialising the stack like this:
int stackInit(intstack_t* self) {
if(malloc(sizeof(self != NULL))) {
self->top = malloc(sizeof(self->top));
self->prev = malloc(sizeof(self->prev));
return 0;
} else {
return 1;
}
}
void stackPush(intstack_t* self, int i) {
self->prev = self->top;
self->top = newElement(i);
}
int stackPop(intstack_t* self) {
int tmp = *self->top;
free(self->top);
self->top = self->prev;
return tmp;
}
int *newElement(int i) {
int *new = malloc(sizeof(i));
*new = i;
return new;
}
My main:
int main()
{
intstack_t stack;
stackInit(&stack);
stackPush(&stack, 1);
stackPush(&stack, 2);
stackPush(&stack, 3);
stackPop(&stack);
printf("stackTop: %i \n", stackTop(&stack));
stackPop(&stack);
printf("stackTop: %i \n, stackTop(&stack));
}
While I can push onto the stack, only the first pop yields the desired output. When I pop again the result is something completely different.
stackTop: 0
stackTop: 1
stackTop: 2
stackTop: 3
stackTop: 2
stackTop: 34792624
Could someone please point me in the right direction, as I dont see where I'm going wrong?
if(malloc(sizeof(self != NULL))) is nonsense code. I can't even make out any sense of your intention here. You need to store the allocated data somewhere and sizeof(self != NULL) is the size of a boolean expresion...
Inside int stackInit(intstack_t* self) you don't return the allocated pointer to the caller, so no matter what you do inside that function it won't get returned to the caller.
It is not clear why you must dynamically allocate the stack itself in the first place. intstack_t stack; already allocates this variable on the stack (the program's stack) before you call stackInit(&stack);.
You must free() memory that you allocate.
And so on. Overall, the code makes no sense at all. It would seem that you are trying to write this program through trial & error programming, which will never work.
One essential problem is that struct intstack_t does not contain any pointer to intstack_t - the previous element in the stack. It only contains pointers to two ints. That is, your implementation of stack cannot store more than two ints at all.
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).
In one function I used malloc :
void name1(struct stos* s)
{
s = malloc (4 * sizeof (int));
}
And everything is ok. But later I used realloc
void name2(struct stos* s)
{
s->size = 2*(s->size);
s = realloc (s, (s->size + 1) * sizeof (int));
}
and I get invalid free/delete/realloc in valgrind and realloc returns NULL.
Declaration of Structure and rest of program is:
struct stos
{
int top;
int size;
int stk[];
};
void name1(struct stos* s);
void name2(struct stos* s);
int main()
{
struct stos stosik;
struct stos* s;
s = &stosik;
name1(s);
//some operations on the array and int top here
name2(s);
}
What did I do wrong here? I looked for what might have gone wrong for quite long, read quite a few articles about pointers, malloc/realloc etc. but with no result. I would be really grateful, if someone could help me.
The problem is slightly subtle and caused by a combination of two things. Let's start here:
struct stos stosik;
struct stos* s;
s = &stosik;
name1(s);
First, you make s point to an a valid chunk of memory that is allocated on the stack (stosik) and then you call name1 passing into s. Let's look at what name1 looks like:
void name1(struct stos* s)
{
s = malloc (4 * sizeof (int));
}
Hmm, we can see that name1 takes in a pointer to a struct stos called s; inside that function, we are allocating some memory and making s point to it. This is a problem.
First of all, note that s already points to a valid chunk of memory. So using a malloc here is suspicious. It will cause a subtle bug that will actually hide the real bug in your program, which is bad. So, let's remove stosik completely:
int main()
{
struct stos* s = NULL;
name1(s);
if(s == NULL)
return -1;
Now, if you run this program, you will see that after you call name1 the variable s still points to NULL. What's happening here?
Well, we are changing the function's LOCAL copy of s (i.e. the s that exists only inside name1)... but the s in main isn't changed! Remember, that we are passing a pointer into name1 but we are passing it by value.
To do what you seem to be trying to do you can do you would have to either pass a pointer to s into name1 (that is, to pass a double pointer) or you should return the result of the malloc from name1 as a return value. Let's look at each of these options:
Passing s in via a double pointer
void name1(struct stos **s)
{
/* sanity check */
if(s == NULL)
return;
/* now, allocate enough space for four integers and make
* whatever s points to, point to that newly allocated
* space.
*/
*s = malloc(4 * sizeof(int));
}
And calling it from main requires us to use the "address-of" operator:
struct stos *s = NULL;
/* we need to pass a pointer to s into name1, so get one. */
name1(&s);
/* malloc can fail; check the result! */
if(s == NULL)
return -1;
Returning a pointer to the allocated memory from name1
struct stos *name1()
{
return malloc(4 * sizeof(int));
}
Calling this from main is slightly easier:
struct stos *s = name1();
/* malloc can fail; check the result! */
if(s == NULL)
return -1;
Changing your code to what I show you here will fix this issue (but there may be others) but let me touch briefly upon something else:
The other bug
The crash you encounterd crops up partially because of the problem we just covered; another issue is that inside name2 you are calling realloc. The pointer you pass into realloc however, is not a pointer that you got back from malloc or realloc, which is what realloc expects. It points to stosik instead. So that code causes undefined behavior and after that anything can happen.
If you're lucky (it seems you were), it will just crash right then and there and if you're not... well, who knows what will happen?
if you want to dynamically allocate s in name1 you need it to be declared as name1(struct stos** s) and pass pointer to the pointer where the allocated memory should appear.
Your main allocates stosik staticaly, meaning you don't need to do any further dynamic allocation. Then when you try doing name1(statically allocated mem) it does … um, something. I don't know what, but certainly not what you expect.