In a project, I was asked to create an INT128 type using int32_t and make postfixed calculations with them. I was using a generic stack to keep track of the operands. The code is below:
typedef struct int128
{
int32_t byteArray[4];
} INT128;
typedef struct node{
void *value;
struct node *bottom;
} NODE;
typedef struct stack{
int size;
size_t dataType;
NODE *top;
} STACK;
I used memcpy() to copy the value of an INT128 to the stack and back. It worked well when the stack had only char variables, but the results were completely different with the INT128 type.
I'm not so familiar with memory manipulation, so theres probably something I'm not seeing here.
Thanks!
Edit:
Sorry guys...im using the functions below to push and pop data from the stack:
void push(STACK *machine,void *pushed)
{
NODE *newNode = malloc(sizeof(NODE));
newNode->value = malloc(machine->dataType);
memcpy(newNode->value,pushed,sizeof(machine->dataType));
newNode->bottom = machine->top;
machine->top = newNode;
machine->size++;
}
void pop(STACK *machine, void *poppedValue)
{
if(machine->top == NULL)
{
printf("WARNING: empty stack!\n");
}
else
{
NODE *popped = machine->top;
memcpy(poppedValue,popped->value,machine->dataType);
machine->top = popped->bottom;
free(popped->value);
free(popped);
machine->size--;
}
}
I'm initializing the stack like:
STACK *numStack = createStack(sizeof(INT128));
And using the push/pop functions normally.
There's a problem here:
newNode->value = malloc(machine->dataType);
memcpy(newNode->value,pushed,sizeof(machine->dataType));
You allocate machine->dataType bytes, but then you copy sizeof machine->dataType bytes. These may be different quantities, either causing a buffer overflow or causing bad behaviour due to not copying enough bytes.
I guess you probably meant to not use sizeof in the second line.
Related
What I did :
I added a pointer in the parameter of malloc(struct Node *) which is usually malloc(struct Node).
Problem :
When I am allocating memory for the size of a pointer then how the code is working?
malloc() is allocating 8 bytes of memory and returning the pointer
So the pointer points to an 8 bytes memory block which but further I am storing more data in it.
struct Node
{
int data;
struct Node *next;
};
struct Node *GetNode(int data)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node *));
node->data = data;
node->next = NULL;
return node;
}
Difference in size:
I know that malloc is allocating different sizes because I did this
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void main(){
int i = sizeof(struct Node);
int j = sizeof(struct Node *);
printf("%d,%d", i, j);
}
Output
16,8
What you've done is undefined behavior. It could work (on some systems, on certain days of the week), or it could crash, or it could produce incorrect results in seemingly unrelated calculations.
Imagine you rent a garage space for your truck, but to save money you request a space for a car. What happens when you drive your truck in? Maybe it fits, maybe you wreck the truck, maybe you destroy the garage.
So don't do that, and to help you find cases where you've made similar mistakes, build with Address Sanitizer. It will log when you access memory in an invalid way.
UB is a fickle mistress. Sometimes agreeable; sometimes not.
That is why you should use a syntax that makes it less likely to make mistakes:
struct Node *node = (struct Node *)malloc(sizeof(struct Node *)); // bad
struct Node *node = malloc( sizeof *node ); // good
No casting, and no redundancy.
I would even recommend using typedef's to free yourself from "struct, struct, struct".
typedef struct s_node
{
int data; // use more indentation, please. whitespace is cheap.
struct s_node *next;
} Node_t;
/* ... */
Node_t *node = malloc( sizeof *node ); // better
Finally, a lot of hours are wasted tracking down bugs that appear and disappear. Until performance becomes a real issue that you understand, I'd recommend using calloc() as the go-to allocation function:
Node_t *node = calloc( 1, sizeof *node ); // best
You can sleep easier knowing the byte values will be repeatable from run to run.
I've created a Stack structure in C. When the stack is initialized with a value, I am able to print it back and receive the correct output. However, after pushing a new string, the print function prints what appears to be a random character (ASCII 177).
Originally, I implemented this project with pointers, but I was unable to get it working. Instead, I opted to only use a pointer for the Node *nodes member of Stack. That way, when I need to grow the stack, I can just multiply the amount of memory required by Stack.size. However, this approach has not worked yet either.
#define MAX_DATA 64
struct Node{
char val[MAX_DATA];
};
struct Stack{
int size;
struct Node *nodes;
};
These are used as follows:
struct Node node = {.val = "Test"};
struct Stack stack = newStack(node);
printStack(stack);
The newStack function initializes nodes properly. For the sake of inclusion:
struct Stack newStack(struct Node node)
{
struct Stack stack;
stack.size = 1;
stack.nodes = (struct Node*) malloc(sizeof(struct Node));
stack.nodes[0] = node;
return stack;
}
The stack is then printed iteratively in printStack(), with stack.size being the upper bound of the for-loop.
The trouble comes when I try to run:
struct Node node2 = {.val = "Test1"};
push(stack, node2);
printStack(stack);
The push function aims to create a temporary stack and assign the value of the stack to it. After this, the size is incremented, the pointer to the nodes is freed, and new memory is allocated, with room for a new member at the end.
void push(struct Stack stack, struct Node node)
{
struct Stack temp_stack = stack;
stack.size += 1;
free(stack.nodes);
stack.nodes = (struct Node*) malloc(sizeof(struct Node) * stack.size);
for(int i = 0; i < temp_stack.size; i++){
stack.nodes[i] = temp_stack.nodes[i];
}
stack.nodes[stack.size - 1] = node;
}
Needless to say, this doesn't execute properly.
The expected output would be:
Test
Test1
But, instead, I receive only ASCII-177. It is also worth noting that the execution hangs after it prints that and moves to the new line. This results in Aborted (core dumped).
Am I improperly freeing and re-allocating memory? Any help would be appreciated. Thank you in advance!
It's worth remembering that in C, passing a struct to a function is pass-by-value, i.e., the function gets a copy of the struct. All members of the struct, including pointer variables (but not whatever the pointer references), are duplicated.
So in the push function, think about what happens to the original when you modify this copy (e.g., stack.size += 1, and also when you free() the stack.nodes.
Thank you to peekay for the recommendations. I ended up doing a re-write. It became quite a bit simpler. I did remove a layer of "visibility" by storing the nodes as a pointer, but I suppose this implementation is a bit more true to the data structure.
Node is implemented as a means to hold data, and the user doesn't interact with it directly. It also points to the following Node. Stack is implemented to hold the top Node, and also the size of the Stack.
Node:
struct Node{
char val[MAX_DATA];
struct Node *next;
};
Stack:
struct Stack{
struct Node *top;
int size;
};
Push:
void push(struct Stack *stack, char *newVal)
{
struct Node *newNode;
newNode = (struct Node*) malloc(sizeof(struct Node));
strcpy(newNode->val, newVal);
newNode->next = stack->top;
stack->top = newNode;
stack->size++;
}
Usage:
struct Stack stack;
newStack(&stack);
push(&stack, "Test");
push(&stack, "Test1");
push(&stack, "Test2");
push(&stack, "Test3");
Complete Code
Updated, accessible Nodes
I have to make a tree that has one types of values in all nodes except leaves and I'm not sure how to do that or is it even possible. E.g. int in all nodes but char in leaves. I'm new at programming so I would really appreciate your help. Thanks
As in your case it is known what the nodes store (ints in nodes and chars in leaves), it is sufficient to check if a node is a leaf, i.e. if left and right are null. Then use a union for value:
struct MYTREE {
struct MYTREE *left, *right;
union {
char *charval;
int intval;
} value;
};
I partially agree with Lundin and Paul. I would keep the data as void*, and check a node to see if it's a leaf by checking the right & left to be NULL or not. Here is something simple to begin with:
#include <string.h>
typedef struct node node;
struct node {
node* right;
node* left;
void* data;
};
int isLeaf(node* n)
{
return n->right == NULL && n->left == NULL;
}
/* you can also make the two functions below a macro, but that's off-topic */
void addInt(node* n, int i)
{
n->data = malloc(sizeof(int));
memcpy(n->data, &i, sizeof(int));
}
void addChar(node* n, char i)
{
n->data = malloc(sizeof(char));
memcpy(n->data, &i, sizeof(char));
}
node* node_new()
{
node* root = malloc(sizeof(node));
root->right = NULL;
root->right = NULL;
}
int main()
{
node* root = node_new();
addInt(root, 3);
/* assume you have some node* n1 */
if (n1->isLeaf())
addChar(n1, 't');
}
The canonical way to store a generic type would be this:
typedef enum
{
TYPE_INT,
TYPE_STR,
} type_info_t;
typedef struct node_t
{
struct node_t* left;
struct node_t* right;
void* data;
type_info_t type;
} node_t;
...
int some_value = 1;
node_t node1 = {NULL, NULL, &some_value, TYPE_INT};
node_t node2 = {NULL, NULL, "hello", TYPE_STR};
You should avoid creating "variants" by using unions, doing so is bad practice:
Variants don't scale well at all during maintenance. If you need to add a larger type than those present, the data will grow accordingly. A variant can never be smaller than its largest member + padding bytes.
They are inefficient, allocating more memory than needed, including padding for the worst case.
The different types in a variant do not necessarily have the same alignment requirements, if they are of different sizes. The alignment within in variant is unspecified. Similarly, endianess could be an issue.
Code using variants can be hard to read and understand. One can make mistakes such as first writing a small type, then reading a larger type, with the result that the larger type partially contains indeterminate data.
You can only initialize one member in the variant explicitly. This means that if the variant was initialized by setting member x, and is then used by accessing member y, then member y could contain an indeterminate value.
(The above covers most of the rationale from MISRA-C:2012 rule 19.2)
I wanted to make an array of stacks in C, where I should be able to retain individual stacks and their respective information. I currently have the following implementation, which only works for one stack. How can I modify the functions push and pop to achieve multiple stacks each using the same function.
(I was easily able to do this in Java, as I could create a class, but I have no idea in C)
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *first = NULL;
void push(int x) {
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->next = first;
first = newnode;
}
int pop() {
int temp = first->data;
first = first->next;
return temp;
}
You have a memory leak in your code in the pop() function. You should free the memory that you have malloc'd.
Taking advice from #Jongware's comments below your question.
Here's a new version of the push() and pop() functions.
#include <stdlib.h>
struct node {
int data;
struct node *prev;
};
void push(struct node **stack, int x) {
if (stack != NULL)
{
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->prev = *stack;
*stack = newnode;
} else
{
// You didn't give me a valid pointer to a stack, so I'm ignoring you!
}
}
int pop(struct node **stack) {
int temp = 0; // This is the default value that is returned when there is an error.
struct node *oldnode;
if (stack != NULL)
{
if (*stack != NULL)
{
oldnode= *stack;
temp = oldnode->data;
(*stack) = oldnode->prev;
free(oldnode);
} else
{
// The stack is empty. I will just ignore you and return the default value for temp.
}
} else
{
// You didn't give me a valid pointer to a stack so I'm ignoring you and returning the default value of 0 for temp!
}
return temp;
}
And here's an example of how to use them:
#include <stdio.h>
int main()
{
struct node *stack1 = NULL, *stack2 = NULL;
int value;
// Push some values onto the stacks
printf("Pushing 7 and then 8 onto stack1\n");
push(&stack1, 7);
push(&stack1, 8);
printf("Pushing 3 onto stack2\n");
push(&stack2, 3);
// Pop and print both stacks
value = pop(&stack2);
printf("Popped %d from stack2\n", value);
value = pop(&stack1);
printf("Popped %d from stack1\n", value);
value = pop(&stack1);
printf("Popped %d from stack1\n", value);
return 0;
}
As for where you should be declaring your stack pointers that is really up to you and how you intend to use them.
Have a read about C variable scope for some options and how you might use them.
Also, I will have to include a warning with declaring these pointers inside functions. In whichever function you declare your pointer you must make sure that you pop everything off the stack before you exit the function, otherwise you will lose the pointer and leak all the allocated memory. If this is not what you want, or you want the pointer to outlive the function then you can declare the pointer globally or pass it around, making sure that everything is popped off the stack before your program exists or loses the pointer.
Another thing that you might want to consider is what happens when you use pop() on an empty stack? The implementation that I have given you simply returns 0 and ignores you. You might want to handle that a little better.
You can only have one stack because you defined it as a global variable:
struct node *first = NULL;
In Java you would have used a class. In C, you can likewise do "object based" programming by defining an abstract data type which holds your instance variables, instead of using global variables:
struct stack {
struct node *first;
};
there are no class features like constructors or destructors, so you write functions to initialize a stack, destroy a stack and so forth. To achieve multiple instantiation, you explicitly pass a stack * argument to each function in the stack module.
You might want to name your functions in some consistent way, like stack_init, stack_cleanup, stack_push and so on.
There are design questions to settle such as: does the caller allocate struct stack, for which you provide stack_init function? Or do you provide a one-step stack_alloc function that allocates and returns a stack? Or perhaps both, so the user can choose performance or convenience?
void stack_init(struct stack *);
void stack_cleanup(struct stack *);
struct stack *stack_alloc(void); /* also calls stack_init on new stack */
void stack_free(struct stack *); /* calls stack_cleanup, then frees */
It's possible to do information hiding in C, whereby you can completely conceal from the client code (which uses the stack module) what a struct stack is.
However, if you provide a stack_init, then the client has to know how large a stack is, since it provides the memory for it. Generally, modules which completely hide an implementation also hide how large it is, and so provide only a stack_alloc and stack_free type interface.
An advantage of that is that client code doesn't have to be recompiled if the stack module is changed and the structure is larger. This is very good if you're writing a widely-used library: it is easy for users to upgrade or possibly downgrade.
However, revealing the implementation allows for more efficient code, since the client has the freedom to choose memory management for stacks. Stacks can be declared as local variables in automatic storage ("on the stack", so to speak), statically as global variables, or packed into arrays.
The user can do things like:
{
struct stack temp_stack;
stack_init(&temp_stack); /* stack is good to go! */
/* ... use stack ... */
stack_cleanup(&temp_stack); /* don't forget to clean up */
}
and things like:
struct stack array_of_stacks[42];
int i;
for (i = 0; i < 42; i++)
stack_init(&array_of_stacks[i]); /* no memory allocation taking place */
All this code has a compile-time dependency of the definition of struct stack; whenever struct stack is touched, it must be recompiled.
Note that if the above struct stack definition is the exact definition for a stack (the only property of a stack is that it has a pointer to a top node which can be null) then, physically speaking, a struct stack * pointer is actually a pointer to a pointer. We can use a typedef name to write the code so that we can use either definition:
/* Alternative "A" */
typedef struct node *stack_t; /* a stack_t type is a pointer to a node */
/* Alternative "B" */
typedef struct stack {
struct node *top;
} stack_t; /* stack_t is a structure containing a pointer to a node */
Either way, the API in terms of stack_t then looks like this:
void stack_init(stack *s);
int stack_push(stack *s, int item);
or whatever. If stack is a pointer (alternative "A" above) then stack *s is a pointer-to-pointer, and so your code will be full of pointer-to-pointer manipulation.
If you're not comfortable with pointer-to-pointer syntax all over the place, then you can give yourself a macro to pretend that it's a structure anyway.
/* Alternative "A" */
typedef struct node *stack_t; /* a stack_t type is a pointer to a node */
#define stack_top(s) (*(s)) /* dereference stack s to obtain the top pointer */
/* Alternative "B" */
typedef struct stack {
struct node *top;
} stack_t; /* stack_t is a structure containing a pointer to a node */
#define stack_top(s) ((s)->top) /* dereference struct pointer to get top pointer */
In the code you can then do things like:
/* push new_node onto stack */
new_node->next = stack_top(s);
stack_top(s) = new_node;
If you consistently use the stack_top accessor, you can now flip the representation of the stack type between alternative "A" and "B" without rewriting any of your code (only recompiling it).
Some nit-picky C programmers will cringe at stack_top(s) = new_node since it looks like a function call is being assigned (which is impossible in C without using macros to bend the language), and prefer a "setter" function for that stack_top_set(s, new_node). That's mostly just outdated, parochial thinking.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int Item;
#define ItemFormat "%d"
struct node {
Item data;
struct node *next;
};
typedef struct node *Stack;
void push(Stack *st, Item x){
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->next = *st;
*st = newnode;
}
bool isEmpty(Stack st){
return st == NULL;
}
Item pop(Stack *st) {
if(!isEmpty(*st)){
struct node *p = *st;
Item value = p->data;
*st = p->next;
free(p);
return value;
}
fprintf(stderr, "Stack is Empty!\n");
return (Item)0;
}
bool inputItem(Item *x){
int stat;
if(1==(stat=scanf(ItemFormat, x)))
return true;
if(stat == EOF)
return false;
scanf("%*[^\n]");
return false;
}
void printItem(Item x){
printf(ItemFormat, x);
}
int main(void){
Stack st = NULL, array[5] = { NULL };
Item x;
while(inputItem(&x)){
push(&array[1], x);
}
while(!isEmpty(array[1])){
x = pop(&array[1]);
printItem(x);
printf("\n");
}
/*
while(inputItem(&x)){
push(&st, x);
}
while(!isEmpty(st)){
x = pop(&st);
printItem(x);
printf("\n");
}
*/
return 0;
}
The static implemetation of two stacks in a single array in C looks something like this...the stack structure will have two top variables top1 and top2.
struct stack
{
int data[MAX];
int top1,top2;
}s;
top1 is initialized to -1 while top2 is initialized to MAX
Overflow condtitions:
1]
if((s->top1)+1==s->top2)
printf("Stack 1 overflow\n");
2]
if((s->top2)-1==s->top1)
printf("Stack 2 overflow\n");
The underflow conditions become pretty obvious. This method may not be memory efficient since we might run out of storage space in the array but it is the basic fundamentals of multiple stacks in a single array.
I wrote a quick generic linked list, simple stuff. But I have a bug and I cannot spot what it is complaining about. Pertinent code:
typedef struct _node {
void *data;
struct _node *next;
} node;
typedef struct _queue {
node *root;
node *last;
unsigned int length;
} queue;
node * find_node(void *data, int size, queue *q)
{
node *n;
for(n=q->root;n;n=n->next)
if(memcmp(data, n->data, size)==0)
return (n);
return (NULL);
}
Testing it:
queue q = {NULL, NULL, 0};
node *n;
int data[QUEUEMAX];
int i;
/* insert bunch of ints into queue */
for(i=0;i<QUEUEMAX;i++) {
data[i] = give_me_a_number();
n = alloc_node();
n->data = data[i];
insert_into(n, &q);
}
printf("list size = %d.\n", q.length);
/* print out, make sure they're there */
for(n=q.root;n;n=n->next)
printf("data = %d\n", (int)n->data); //*(int *)n->data didn't work, segfault?
/* find a specific node */
node *nd = find_node(&data[10], sizeof(int), &q);
/* remove it */
rm_node(nd, &q);
Running it:
$ ./test
list size = 256.
data = 10
data = 11
data = 12
data = 13
data = 14
data = 15
data = 16
... blah blah (256 lines)
Segmentation Fault
gdb says the problem is the memcmp() in find_node(). I think gcc is whining about the n->data being passed to memcmp(). Any ideas? Also, I was getting a segfault trying to do int x = *(int *)n->data but this seems valid to me, non?
In this code:
n->data = data[i];
You are currently setting the void* data pointer to be data[i] but you really want to set it to the address of data[i] so you need to do:
n->data = &data[i];
That is also why you got a segfault on your cast.
Segmentation Fault happens when you try to dereference NULL pointer. If you know the line where it happens verify that there no NULL there, example int x = *(int *)n->data will generate SEGFAULT if n is NULL or n->data is NULL
Assuming that your memory allocation functions are working, most likely n->data is NULL, and therefore you can't access it. Also, why are you passing the data array as &data[10]? Why not just use data since the identifier of an array is a pointer to its first location?
It looks like you are being inconsistent in whether your data is a pointer or if its a pointer thats being casted to an int. You are passing a int (since the pointer is basically a int cause of the cast).
memcpy naturally wants a void *, not an int.
So the solution really is to pass a pointer to your int in data and make everything else work with that.
Also, the memcmp call in find_node will sometimes compare too much data. You're using memcmp with the size of the data you're searching for. If the data in the current node is shorter than that, memcmp will go beyond it, into forbidden territory. (The test code you posted won't usually trip this bug, because most of the data fields have the same length.) You need to add a length field to each node, and use the minimum of both lengths in memcmp.
You're assigning an int variable
n->data = data[i];
To what it is supposed to be a pointer
typedef struct _node {
void *data;
struct _node *next;
} node;