Issue with PHP pop( ) function [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
So I'm having an issue with my pop() function, when running my program, the first time I call the pop() function it returns the item no problem, but when it tries to pop the second item in succession, it fails. I can't seem to figure out why, is there something I'm missing in my function?
#define DEFAULT_CAPACITY 16
struct stack {
size_t capacity;
size_t size;
stack_item *data;
};
stack *new_stack (void) {
stack *this = malloc (sizeof (stack));
assert (this != NULL);
this->capacity = DEFAULT_CAPACITY;
this->size = 0;
this->data = calloc (this->capacity, sizeof (stack_item));
assert (this->data != NULL);
return this;
}
void free_stack (stack *this) {
assert (empty_stack (this));
free (this->data);
free (this);
}
static bool full_stack (stack *this) {
return this->size == this->capacity;
}
static void realloc_stack (stack *this) {
size_t old_capacity = this->capacity;
this->capacity *= 2;
this->data = realloc (this->data, this->capacity);
memset (this->data + old_capacity, 0, old_capacity);
assert (this->data != NULL);
}
void push_stack (stack *this, stack_item item) {
if (full_stack (this)) realloc_stack (this);
//increase size of stack
this->data[this->size] = item;
this->size++;
}
stack_item pop_stack (stack *this) {
assert (! empty_stack (this));
printf("Stack size: %lu\n", this->size);
return this->data[this->size--];
}

Depends on what you mean by "fail".
There are numerous reasons it could fail, such as (by no means exhaustive):
code for pushing data is incorrect.
you haven't created a big enough capacity.
you haven't pushed enough items to pop (stack underflow).
The first thing you should do is create a dump_stack function for debugging, along the lines of:
void dump_stack (char *desc, stack *this) {
printf ("%s: size/capacity: %lu/%lu\n",
desc, this->size, this->capacity);
for (size_t idx = 0; idx < this->size; idx++) {
// print out this->data[idx], depends on data type
}
}
This will greatly assist in figuring out where your problem lies, if you call it after each stack operation (push, pop, peek, clear, dup, rot, 2dup, 3rot, and so on).
Now that you've added some more code, there's a few things you need to look at.
First, your stack_item type. Unless this is exactly the same size as char, your memory allocation functions are incorrect. For example, if it's a four-byte integer, you will need to allocate four times as much memory as you currently are. This can be fixed by multiplying the allocations by sizeof(stack_item).
You've done this with the initial calloc call (because you have to provide a size for that) but not in the subsequent realloc ones.
Second, in your realloc_stack function, you really should assert before doing the memset. If, for some reason, the reallocation fails, it's not a good idea to do anything to the memory.
Third, relying on assert to catch errors that may or may not happen at runtime is a bad idea. That's because assert typically does nothing in non-debug code (based on NDEBUG) so, if you run out of memory, you're not going to catch that. You probably need to provide your own error handling stuff in conjunction with exit() (for example).
I'm also not really a big fan of library-type code pulling the rug out from underneath you if it has a problem - I always prefer to have it return an indication to the caller and let that decide what to do (that's why I'll never use GMP in production code since it does exactly that when it runs out of memory).
Fourth, using calloc and memset here is almost certainly a waste since your code knows where the stack end is based on size. Whether those entries above size but below capacity are set to 0 or some arbitrary value is irrelevant since you'll never use them without first setting them to something (with a push operation).

Related

Design Pattern to free an object in C

When programming in C, we usually create data structures that we initialize, then free when it is no longer needed. For instance, if we want to create a dynamic array of double, it is common to declare
struct vector {
double *data;
int size;
int capacity;
}
typedef struct vector vector;
vector *v_new(int n) {
vector *v = malloc(sizeof(vector));
v->data = malloc(n * sizeof(double));
v->size = n;
v->capacity = n;
return v;
}
The question is about the common patterns for a free function. In C, the function free accepts the NULL pointer and does nothing. Is it a common pattern to design v_free functions in such a way, or are they usually expecting a non-NULL pointer? To make it clear, would you expect this implementation
void v_free(vector *v) {
if (v != NULL) {
free(v->data);
}
free(v);
}
or this one ?
void v_free(vector *v) {
free(v->data);
free(v);
}
This question is asked because we began to teach C to undergraduate students in prep school in France, and we don't have that much experience in "C Design Patterns".
Thanks for your advice.
You can't access v->data if v is NULL. So if there is a chance of that, you must do the version which checks for that, which is better written as
void v_free(vector *v) {
if (v != NULL) {
free(v->data);
free(v);
}
}
If v should never be NULL here, it's perhaps better to add an assert to make the assumption explicit:
void v_free(vector *v) {
assert(v != NULL);
free(v->data);
free(v);
}
That way the programmer will notice they are doing something wrong.
Note that neither version detects a dangling pointer, ie. pointer which points to already destroyed object. This includes pointing to memory already freed (ie. you'd have double free here) or by pointer having pointed to local variable which is not in scope any more.
The question is about the common patterns for a free function. In C, the function free accepts the NULL pointer and does nothing. Is it a common pattern to design v_free functions in such a way, or are they usually expecting a non-NULL pointer?
This is going to be a matter of opinion.
My opinion is, unless you have a good reason otherwise, program defensively. Do the thing that will make debugging a mistake easier. Make v_free error on a null pointer. Something as simple as an assert.
void v_free(vector *v) {
assert(v != NULL);
free(v->data);
free(v);
}
Consider if we quietly ignore the null case. Did the caller intend to pass a null pointer, or was it a mistake? We don't know. If it was a mistake, the program continues merrily along and probably mysteriously crashes elsewhere. This makes debugging more difficult.
Consider if we assume v_free will always receive a non-null pointer. If it does free(v->data) is undefined behavior. At best a messy error, at worst the program continues merrily along and probably mysteriously crashes elsewhere. This makes debugging more difficult.
But if we provide an error, the mistake is stopped and revealed. Do the same thing for all your vector functions.
"But what if I want to pass a null pointer?" That should be infrequent, don't optimize for it. Make the caller do the check. If they really need to do it frequently, they can write a little wrapper function.
void v_free_null(vector *v) {
if( v == NULL ) {
return;
}
v_free(v);
}

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(): invalid next size glibc detected

I was implementing stacks using dynamically allocated arrays. Once the array is full I need to reallocate the array and make it twice as big as the initial array.
My code:
typedef int Item;
typedef struct stackImp *Stack;
struct stackImp{
Item * items;
int top;
int maxSize;
Stack createStack (void){
Stack s = malloc(sizeof(struct stackImp));
assert(s != NULL);
s->items = malloc(DEFAULT_SIZE * sizeof(Item));
assert(s->items != NULL);
s->top = 0;
s->maxSize = DEFAULT_SIZE;
return s;
void push (Stack stack, Item item)
.
.
.
if (stack->top < stack->maxSize) {
//Over here I'm checking if the top index is less than the
//maximum Items the array can store. If it's less then it pushes the
//item to the top of the array.
stack->items[stack->top] = item;
stack->top++;
}
else {
//If the index is greater than or equal to the maximum size then
//I realloc a new array which is twice the size of the initial array.
temp = realloc(stack->items, 2*(stack->maxSize) * sizeof(Item));
assert (temp != NULL);
stack->items = temp;
.
.
.
}
When I push items onto the stack it works perfectly fine but when I push on more than the initial maxSize it gives me this error:
It is clear I'm doing something wrong with my realloc function but I am unable to find what.
This is the valgrind output:
Your code is kind of confusing, since stack->top does not actually points to the index of the actual stack top. This might be causing some confusion on other parts of your code, since you have to use stack->items[stack->top-1] and not stack->items[stack->top] to access the top of your stack.
Please double check things like that. This error is probably caused by memory corruption. Learn how to use memory debuggers.
And I recommend that you try to implement stacks using lists instead of arrays.
Since the error is coming from realloc and the memory arena seems to be already corrupted, it's almost certainly something you're doing before this point.
Your best bet is to run it with a memory debugger like valgrind and check if you're overflowing buffers.
It may be the initial allocation of the array of Item objects (or lack thereof), it may be incorrect initialisation of the other fields like top or maxSize. Without the full code, it's a little hard for us to tell so, if you want a definitive answer, you should post all the relevant code.
But a memory debugger should help out greatly, should you not wish to do that.

Structure initialization performance

I am trying to improve performance of my program (running on ARC platform, compiled with arc-gcc. Having said that, I am NOT expecting a platform specific answer).
I want to know which of the following methods is more optimal and why.
typedef struct _MY_STRUCT
{
int my_height;
int my_weight;
char my_data_buffer[1024];
}MY_STRUCT;
int some_function(MY_STRUCT *px_my_struct)
{
/*Many operations with the structure members done here*/
return 0;
}
void poorly_performing_function_method_1()
{
while(1)
{
MY_STRUCT x_struct_instance = {0}; /*x_struct_instance is automatic variable under WHILE LOOP SCOPE*/
x_struct_instance.my_height = rand();
x_struct_instance.my_weight = rand();
if(x_struct_instance.my_weight > 100)
{
memcpy(&(x_struct_instance.my_data_buffer),"this is just an example string, there could be some binary data here.",sizeof(x_struct_instance.my_data_buffer));
}
some_function(&x_struct_instance);
/******************************************************/
/* No need for memset as it is initialized before use.*/
/* memset(&x_struct_instance,0,sizeof(x_struct_instance));*/
/******************************************************/
}
}
void poorly_performing_function_method_2()
{
MY_STRUCT x_struct_instance = {0}; /*x_struct_instance is automatic variable under FUNCTION SCOPE*/
while(1)
{
x_struct_instance.my_height = rand();
x_struct_instance.my_weight = rand();
if(x_struct_instance.my_weight > 100)
{
memcpy(&(x_struct_instance.my_data_buffer),"this is just an example string, there could be some binary data here.",sizeof(x_struct_instance.my_data_buffer));
}
some_function(&x_struct_instance);
memset(&x_struct_instance,0,sizeof(x_struct_instance));
}
}
In the above code, will poorly_performing_function_method_1() perform better or will poorly_performing_function_method_2() perform better? Why?
Few things to think about..
In method #1, can deallocation, reallocation of structure memory add more overhead?
In method #1, during initialization, is there any optimization happening? Like calloc (Optimistic memory allocation and allocating memory in zero filled pages)?
I want to clarify that my question is more about WHICH method is more optimal and less about HOW to make this code more optimal. This code is just an example.
About making the above code more optimal, #Skizz has given the right answer.
Generally, not doing something is going to be faster than doing something.
In your code, you're clearing a structure, and then initialising it with data. You're doing two memory writes, the second is just overwriting the first.
Try this:-
void function_to_try()
{
MY_STRUCT x_struct_instance;
while(1)
{
x_struct_instance.my_height = rand();
x_struct_instance.my_weight = rand();
x_struct_instance.my_name[0]='\0';
if(x_struct_instance.my_weight > 100)
{
strlcpy(&(x_struct_instance.my_name),"Fatty",sizeof(x_struct_instance.my_name));
}
some_function(&x_struct_instance);
}
}
Update
To answer the question, which is more optimal, I would suggest method #1, but it is probably marginal and dependent on the compiler and other factors. My reasoning is that there isn't any allocation / deallocation going on, the data is on the stack and the function preamble created by the compiler will allocate a big enough stack frame for the function such that it doesn't need to resize it. In any case, allocating on the stack is just moving the stack pointer so it's not a big overhead.
Also, memset is a general purpose method for setting memory and might have extra logic in it that copes with edge conditions such as unaligned memory. The compiler can implement an initialiser more intelligently than a general purpose algorithm (at least, one would hope so).

Resources