Assign struct to char array - c

I am trying to create my own malloc but I am stuck on one point. As we know we have to assign struct as a meta data in available space as it is mentioned in this picture.
char heap_space[MEM_BUFFER];
struct myblock
{
struct myblock *next;
struct myblock *prev;
int size;
char *buffer;
}
I have my heap_space which will be my "RAM" . Now I am stuck on one point:-
How to assign my structure myblock to heap_space, and one thing which we should keep in mind that every time when new request will come, the place of the myblock will be changed as per allocated (requested) space.

I'm not sure to understand your problem but why don't you try something like:
#define MEM_BUFFER 4096
#define size_t unsigned int
char heap_space[MEM_BUFFER] = {0};
struct myblock
{
struct myblock *next;
struct myblock *prev;
int size;
char *buffer;
};
void *malloc(size_t size)
{
struct myblock *tmp = heap_space;
if (tmp != 0) // != 0 since NULL is in stdlib
while (tmp->next != 0)
tmp = tmp->next;
struct myblock *new_elem = tmp; //your question I guess
new_elem->prev = tmp;
new_elem->size = size;
new_elem->buffer = new_elem + sizeof(*new_elem);
new_elem->next = new_elem->buffer + new_elem->size;
return (new_elem->buffer);
}
int main()
{
char *str1 = malloc(10);
char *str2 = malloc(10);
strcpy(str1, "Hello");
strcpy(str2, "World");
printf("%s %s\n", str1, str2);
}
You should just think your memory in a different way I guess, where inside your heap_space you can have many things.
If you don't understand something please ask.
You should also use void * and unsigned int instead of int
Furthermore you still have some stuff to do:
Check if the size required is available in your array
Give a little more space in case you want to implement your
realloc
Implement your free function
And if you are on linux, you should try to use brk/sbrk instead of having your 'heap space'. But the greatest thing is to run 'real' programs with your own malloc (using LD_PRELOAD)

If it's C++, you should use myblock *free_ptr = reinterpret_cast<myblock*>(heap_space); to initialize your free pointer, and then initialize the size, next, prev and buffer of free_ptr.
In C, you would use a regular C style cast, struct myblock *free_ptr = (struct myblock*)heap_space;.

You should declare
struct myblock
{
struct myblock *next;
struct myblock *prev;
int size;
char buffer[0];
}
so your malloc will return myblockvar.buffer.

Related

Can I malloc only the exact memory needed for an input string and point it?

I'm making a program where I save input strings from fgets in a list, they have a fixed maximum lenght but can also be shorter; i save them like this:
typedef char line[LINE_SIZE];
struct node{
line *t; //pointer and not just a variable so I can "detach" the allocation to do stuff
struct node *prev;
struct node *next;
};
but, in my program I just do malloc(sizeof(line)) which is an array with the maximum fixed lenght.
My question is, if I were to allocate something like malloc( strlen( str ) + sizeof( ( char )'\0' ) ) to precisely use only the memory needed, how can I point it?
Is it okay using a char* inside the node struct? Do I risk something?
I have heard about flexible arrays inside the structs but I don't want to put the array directly inside the struct, because for the program I need to be able to detach it and then point to it with another pointer
malloc() returns the address it allocated, you can assign the return value to a variable and point it. You don't need to always allocate maximum or the same size of memory even though the variable is the same member of a struct.
char* line=malloc(strlen(str)+1); // +1 for null terminate
strcpy(line, "This is a str"); // points the memory of returned
Using a char* in a struct is absolutely fine. Please treat a member of struct like a plain variable.
struct node
{
char* t;
struct node* prev;
struct node* next;
}
node n;
n.t = malloc(strlen(str) + 1); // it's fine.
strcpy(n.t, "This is a node"); // using the memory you allocated above
n.prev = n.next = NULL;
... // doing some processing
free(n.t); // don't forget to call free() when you're done using the memory.
For your purpose, you must allocate the node structure and the line fragment separately.
Depending on what the rest of the code assumes, you could allocate just the space for the string for each line instead of a full array, but you must change the node structure to use a char *t; instead of a line typedef. Note that it is very confusing to typedef arrays.
The only caveat is you must be careful when modifying these strings as you cannot add any characters at the end, nor insert any characters by moving contents beyond their allocated length. As a rule of thumb, if you reallocate these strings whenever you modify them, you should be safe.
Here is a simple example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *t; //pointer and not just a variable so I can "detach" the allocation to do stuff
struct node *prev;
struct node *next;
};
struct node *read_file(FILE *fp) {
char buf[128];
struct node *head = NULL, tail = NULL, *n = NULL;
while (fgets(buf, sizeof buf, fp)) {
buf[strcspn(buf, "\n")] = '\0'; // strip the trailing newline if present
n = malloc(sizeof(*n));
if (n == NULL)
abort();
n->prev = tail;
n->next = NULL;
n->t = strdup(buf);
if (n->t == NULL)
abort();
if (tail == NULL) {
head = n;
} else {
tail->next = n;
}
tail = n;
}
return head;
}

Struct Pointers Segmentation Fault, How can I solve this?

I have these structures in C:
typedef struct Game{
char* name;
char* team_1;
char* team_2;
int score[2];
} *pGame;
typedef struct Team{
char *name;
int victories;
} *pTeam;
typedef struct node_game{
pGame game;
struct node_game *next;
} *link_game;
typedef struct node_team{
pTeam team;
struct link_team *next;
} *link_team;
typedef struct head{
link_game game_list;
link_team team_list;
} *pHead;
And these functions to go with it:
void initialize(pHead* heads,int m){
int i;
heads = (pHead*)malloc(m*sizeof(pHead));
for (i = 0; i < m; i++)
heads[i] = NULL;
}
//this function is to allocate dynamic memory for a string
char* str_dup(char* buffer){
char* str;
str = (char*) malloc(sizeof(char)*(strlen(buffer)+1));
strcpy(str,buffer);
return str;
}
void add_team(pHead* heads, char* name){
char* name_dup;
link_team new_team = (link_team) malloc(sizeof(struct node_team));
name_dup = str_dup(name);
new_team->team->name = name_dup; //this line gives me segmentation fault
}
int main(){
pHead* heads;
initialize(heads,M);
add_team(heads, "manchester");
return 0;
}
Why is it that the last line of add_team gives me segmentation fault? I've looked at this with the VSC debugger and it seems it should go well. My problem is most likely that I'm not allocating memory when I should, but I can't see where. (also, the function will do more stuff, but it gives me segmentation fault already there).
At the time you do this:
new_team->team->name = name_dup;
You allocated memory for new_team, but not for new_team->team. This means that new_team->team->name dereferences an uninitialized pointer invoking undefined behavior.
You need to allocate space for it first:
link_team new_team = malloc(sizeof(struct node_team));
new_team->team = malloc(sizeof(struct Team));
Or you can change team from a struct Team * to a struct Team and access it directly. You probably want to do the same for game in struct node_game.

Changing a global structure in a function in C

I defined a structure as follows:
typedef struct myStruct{
char *val1;
char *val2;
struct myStruct *prev;
struct myStruct *next;
} myStruct;
I also wrote a function to add a node to this structure:
void add_to_struct(struct myStruct *strct, char *val1,
char *val2){
// create the node for new element
struct myStruct *my_new = malloc(sizeof(struct myStruct));
my_new->val1 = val1;
my_new->val2 = val2;
my_new->next = strct;
my_new->prev = NULL;
strct->prev = my_new;
}
Adding a node to the struct using this function doesn't seem to work though. I guess the problem is that I do not pass my structure (which I defined as a global variable) by reference correctly, but I don't know why. Any idea what I am doing wrong?
EDIT
How I call it:
void main(){
struct myStruct *headPrev = Malloc(sizeof(struct myStruct *));
struct myStruct *headNext = Malloc(sizeof(struct myStruct *));
char *headval1 = Malloc(sizeof(char) * MAXLEN);
char *headval2 = Malloc(sizeof(char) * MAXLEN);
my_struct = Malloc(sizeof(struct myStruct));
my_struct->prev = headPrev;
my_struct->next = headNext;
my_struct->val1 = headval1;
my_struct->val2 = headval2;
newVal1 = "abcd";
newVal2 = "bl";
....
add_to_struct(my_struct,newVal1,newVal2);
}
looks pretty close, just a few minor issues --
my_new should be allocated to be sizeof(struct myStruct)), not cacheElement, no?
also, this looks like a linked list, but you need to return my_new so you can use it as the new head of list.
You're allocating memory using malloc and collecting the address of the memory using my_new variable. So the function is doing nothing effectively. Let me provide an anology. A man comes to ask water at your home. You should either take his bottle, fill it with water and give it back. Or you can give your own bottle to him filled with water. But you're simply taking your own bottle, filling it with water and keeping it to yourself.
You either have to do return my_new or use strct=malloc.... and also change argument of sizeof to myStruct
Try to use void add_to_struct(struct myStruct **strct, char *val1, char *val2).
void add_to_struct(struct myStruct **strct, char *val1,char *val2)
{
// create the node for new element
struct myStruct *my_new = malloc(sizeof(struct myStruct));
my_new->val1 = "abcd";
my_new->val2 = "efgh";
my_new->next = strct;
my_new->prev = NULL;
(*strct)->prev = my_new;
}

Is it possible to generically free linked lists' memory in C

If I have several linked structures in C like:
struct structA {
int a;
int b;
struct structA *next;
}
struct structB {
char a;
int b;
struct structB *next;
}
and I dynamically allocate memory like this:
struct structA *mystructA = (struct structA*) malloc(sizeof(struct structA));
mystructA->next = (struct structA*) malloc(sizeof(struct structA));
struct structB *mystructB = (struct structB*) malloc(sizeof(struct structB));
mystructB->next = (struct structB*) malloc(sizeof(struct structB));
do I always have to free it for each struct type like this:
struct structA *p, *pNext;
for (p = mystructA; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
struct structB *p, *pNext;
for (p = mystructB; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
or is there any generic solution? I assume there is no other solution because the free() procedure must know how many bytes have to be freed. But maybe I'm wrong and someone can teach me better.
The standard way is to make the "list part" the first element of the structure, and let each derived struct share this same prefix. Since the first element is guaranteed to be placed at offset zero this wil work.
Example snippet:
#include <stdlib.h>
#include <string.h>
struct list {
struct list *next;
};
struct structA {
struct list list;
int a;
int b;
};
struct structB {
struct list list;
char a;
int b;
};
void *create_any(size_t size)
{
struct list *this;
this = malloc (size);
if (!this) return this;
memset(this, 0, size);
this->next = NULL;
return this;
}
void free_all_any(struct list **lp) {
struct list *tmp;
while ((tmp = *lp)) { *lp = tmp->next; free(tmp); }
}
#define CREATE_A() create_any(sizeof(struct structA))
#define CREATE_B() create_any(sizeof(struct structB))
#define FREE_A(pp) free_any((struct list **) pp)
#define FREE_B(pp) free_any((struct list **) pp)
int main(void)
{
struct structA *ap;
struct structB *bp;
ap = CREATE_A ();
bp = CREATE_B ();
// some code here ...
FREE_A( &ap);
FREE_B( &bp);
return 0;
}
This is more or less the method used in the linux kernel, but a lot more preprocessor magic is used there. (and there is no malloc there, obviously)
Since free() accepts pointers to void * and structA and structB both have the same size, you can pass both pointer types.
This is, however, not optimal in terms of elegance. You should think about the following questions:
Why do you have two different structs with the same members?
Why do you not have a generic list item type, such as the following:
struct list_node {
void *data;
struct list_node *next;
}
Actually, this is a very interesting question. The part is true that you have to free() each struct type individually, as they have been malloc()-ed individually, and each memory block has been allocated specifically for that type.Also, on some systems char and int have different storage sizes, but you can try a solution like Phillip provided. For more info, read about the doom memory engine. On a side note, please don't cast malloc() in C. The funny thing is that once the program is terminated, the operating system will reclaim the memory, so if you only deallocate the structures near the end of the program, when you don't need them anymore, it may not be necessary to free() them

A simple stack implementation using C

I had written a program in C to implement a simple stack. But I am getting segmentation fault in my program and finding it hard to find out what is wrong. Can any one help,
#include<stdio.h>
#include<stdlib.h>
struct stack_structure{
int stack_array[10];
int stack_pointer;
};
void push_into_stack(struct stack_structure *,int);
int main(){
int no = 8;
struct stack_structure *st;
st->stack_pointer = -1;
push_into_stack(st,no);
return 0;
}
void push_into_stack(struct stack_structure *s,int no){
s -> stack_pointer++;
s -> stack_array[s -> stack_pointer] = no;
}
struct stack_structure *st;
This only creates a pointer to a struct stack_structure. It does not allocate memory for the struct stack_structure itself.
You can try with this:
struct stack_structure st;
st.stack_pointer = -1;
push_into_stack(&st,no);
The other option is to dynamically allocate (and free) that structure:
struct stack_structure *st = malloc(sizeof(struct stack_structure));
...
// when you're done with it
free(st);
See these lines:
struct stack_structure *st;
st->stack_pointer = -1;
You've declared a pointer variable but then you're using it uninitialized. A pointer has to point at something, and this one doesn't have anything to point to. The simplest fix would be to change these lines to:
struct stack_structure st1, *st=&st1;
st->stack_pointer = -1;
You need to malloc some space for the structure:
struct stack_structure *st = malloc(sizeof(struct stack_structure));

Resources