write your own malloc - c

I am writing my own malloc() and i have already figured the following
struct myblock
{
struct myblock *next;
struct myblock *prev;
int isFree;
unsigned availablesize;
char *buffer;
}
and space #define MEM_BUFFER (1024) which will be "my ram".
and if i am not wrong then i would have
char *array[MEM_BUFFER];
to have array of 1024 bytes (kindly correct me if i am wrong).
As we know that MEM_BUFFER will also contain the matadata of occupied space. I am bit confused that how should i start.
This is my main question.
should i assign the struct to the array on each allocation request (if yes then from struct char array ?) .
should i handle double linked list on heap and skip sizeof(myblock) bytes from the array.
I am thinking on this solution for last 2 days and I am still confused.

No,
char *array[MEM_BUFFER];
is not an array of 1024 bytes (unless MEM_BUFFER is set to 1024 / sizeof (char *)) typically. It's an array of MEM_BUFFER character pointers.
You need just:
char array[MEM_BUFFER];
although a better name might be heap_space.
To make it consist of blocks, you'd need an additional pointer that is the first block:
struct myblock *heap = (struct myblock *) heap_space;
Then you can initialize that:
heap->next = NULL;
heap->prev = NULL;
heap->isFree = 1;
heap->availablesize = sizeof heap_space - sizeof *heap;
Not sure what struct myblock.buffer should do, I put the blocks inside the heap so the user memory for a block is at (void *) (block + 1);

Related

c: reallocate memory pointed by a struct member

#define DEFAULT_SIZE 100
struct my_struct {
struct some_struct *ptr;
size_t len;
char buf[0];
};
struct my_struct *s;
s = malloc(sizeof *s + DEFAULT_SIZE);
...
Now, assuming I want to expand the buf memory. Do I need to re-create struct my_struct * with realloc() call? Can't I simply reallocate memory occupied by buf, i.e. :
realloc(s->buf, 2* DEFAULT_SIZE);
No. You can only realloc a pointer returned by malloc. malloc gave you the pointer to the entire structure, so that is what you may realloc.

what's the correct way to malloc struct pointer using sizeof?

Imagine I've the following struct
struct Memory {
int type;
int prot;
};
typedef struct Memory *Memory;
How would I initialise it using malloc()?
Memory mem = malloc(sizeof(Memory));
or
Memory mem = malloc(sizeof(struct Memory));
What is the correct way to allocate that?
Your struct declaration is a bit muddled up, and the typedef is wrong on many levels. Here's what I'd suggest:
//typedef + decl in one
typedef struct _memory {
int type;
int prot;
} Memory;
Then allocate like so:
Memory *mem = malloc(sizeof *mem);
Read the malloc call like so: "Allocate the amount of memory required to store whatever type mem is pointing to". If you change Memory *mem to Memory **mem, it'll allocate 4 or 8 bytes (depending on the platform), as it now stands it'll probably allocate 8 bytes, depending on the size of int and how the compiler pads the struct check wiki for more details and examples.
Using sizeof *<the-pointer> is generally considered to be the better way of allocating memory, but if you want, you can write:
Memory *mem = malloc(sizeof(Memory));
Memory *mem = malloc(sizeof(struct _memory));
They all do the same thing. Mind you, if you typedef a struct, that's probably because you want to abstract the inner workings of something, and want to write an API of sorts. In that case, you should discourage the use of struct _memory as much as possible, in favour of Memory or *<the-pointer> anyway
If you want to typedef a pointer, then you can write this:
typedef struct _memory {
int type;
int prot;
} *Memory_p;
In which case this:
Memory_p mem = malloc(sizeof *mem);
might seem counter intuitive, but is correct, as is:
Memory_p mem = malloc(sizeof(struct _memory));
But this:
Memory_p mem = malloc(sizeof(Memory_p));
is wrong (it won't allocate the memory required for the struct, but memory to store a pointer to it).
It's a matter of personal preference, perhaps, but I personally find typedefs obscure certain things. In many cases this is for the better (ie FILE*), but once an API starts hiding the fact you're working with pointers, I start to worry a bit. It tends to make code harder to read, debug and document...
Just think about it like this:
int *pointer, stack;
The * operator modifies a variable of a given type, a pointer typedef does both. That's just my opinion, I'm sure there are many programmers that are far more skilled than me who do use pointer typedefs.
Most of the time, though, a pointer typedef is accompanied by custom allocator functions or macro's, so you don't have to write odd-looking statements like Memory_p mem = malloc(sizeof *mem);, but instead you can write ALLOC_MEM_P(mem, 1); which could be defined as:
#define ALLOC_MEM_P(var_name, count) Memory_p var_name = malloc(count * sizeof *var_name)
or something
Both
typedef struct Memory * Memory;
and
Memory mem = malloc (sizeof (Memory));
are wrong. The correct way to do it is :
typedef struct memory
{
int type;
int prot;
} *MEMPTR;
or
struct memory
{
int type;
int prot;
};
typedef struct memory *MEMPTR;
The name of the structure should be different than the name of a pointer to it.
This construction
struct {
int type;
int prot;
} Memory;
defines an object with name Memory that has type of unnamed structure.
Thus the next construction
typedef struct Memory *Memory;
defined 1) a new type struct Memory that has nothing common with the definition above and the name Memory. and 2) another new type name Memory that is pointer to struct Memory.
If the both constructions are present in the same compilation unit then the compiler will issue an error because name Memory (the name of the pointer) in the typedef declaration tries to redeclare the object of the type of the unnamed structure with the same name Memory.
I think you mean the following
typedef struct Memory {
int type;
int prot;
} Memory;
In this case you may use the both records of using malloc like
Memory *mem = malloc( sizeof( Memory ) );
and
struct Memory *mem = malloc( sizeof( struct Memory ) );
or
Memory *mem = malloc( sizeof( struct Memory ) );
or
struct Memory *mem = malloc( sizeof( Memory ) );
because now the two identifiers Memory are in two different name spaces, The first one is used with tag struct and the second is used without tag struct.

Pointer manipulation to access elements in a struct

Given the below simple code, where you have process_payload is given a pointer to the payload portion of the packet, how do you access the header portion? Ideally the caller should simply give a pointer to full packet from beginning, but there are cases where you don't have the beginning of the message and need to work backwards to get to the header info. I guess this question becomes a understanding of walking through the memory layout of a struct.
The header computes to 8 bytes with sizeof operation. I assume Visual C++ compiler added 3 bytes padding to header.
The difference between pptr and pptr->payload is decimal 80 (not sure why this value??) when doing ptr arith (pptr->payload - pptr). Setting ptr = (struct Packet*)(payload - 80) works but seems more a hack. I don't quite understand why subtracting sizeof(struct header) doesn't work.
Thanks for any help you can give.
struct Header
{
unsigned char id;
unsigned int size;
};
struct Packet
{
struct Header header;
unsigned char* payload;
};
void process_payload(unsigned char* payload);
int main()
{
struct Packet* pptr = (struct Packet*)malloc(sizeof(struct Packet));
pptr->payload = (unsigned char*)malloc(sizeof(unsigned char)*10);
process_payload(pptr->payload);
return 1;
}
// Function needs to work backwards to get to header info.
void process_payload(unsigned char* payload)
{
// If ptr is correctly setup, it will be able to access all the fields
// visible in struct Packet and not simply payload part.
struct Packet* ptr;
// This does not work when intuitively it should?
ptr = (struct Packet*)(payload - sizeof(struct Header));
}
It's because in main you allocate two pointers, and pass the second pointer to the process_payload function. The two pointers are not related.
There are two ways of solving this problem, where both include a single allocation.
The first solution is to used so called flexible arrays, where you have an array member last in the structure without any size:
struct Packet
{
struct Header header;
unsigned char payload[];
};
To use it you make one allocation, with the size of the structure plus the size of the payload:
struct Packet *pptr = malloc(sizeof(struct Packet) + 10);
Now pptr->payload is handled like a normal pointer pointing to 10 unsigned characters.
Another solution, which is a mix of your current solution and the solution with flexible arrays, is to make one allocation and make the payload pointer to point to the correct place in the single allocated memory block:
struct Packet
{
struct Header header;
unsigned char *payload;
};
// ...
struct Packet *pptr = malloc(sizeof(struct Packet) + 10);
pptr->payload = (unsigned char *) ((char *) pptr + sizeof(struct Packet);
Note that in this case, to get the Packet structure from the payload pointer, you have to use sizeof(Packet) instead of only sizeof(Header).
Two things to note about the code above:
I don't cast the result of malloc
sizeof(char) (and also the size of unsigned char) is specified to always be one, so no need for sizeof

What is the proper way to use memset on a struct element?

I'm trying to use memset on a struct element like so:
memset( &targs[i]->cs, 0, sizeof( xcpu ) );
However, doing so gives me a segmentation fault. I neither understand why this is failing, nor how I can make it work. What is the proper way to use memset on an element of a struct, and why does my method not work?
Line which allocates memory for targs:
eargs **targs = (eargs **) malloc(p * sizeof(eargs *));
Struct definitions for struct element cs (xcpu_context) and struct targs (execute_args):
typedef struct xcpu_context {
unsigned char *memory;
unsigned short regs[X_MAX_REGS];
unsigned short pc;
unsigned short state;
unsigned short itr;
unsigned short id;
unsigned short num;
} xcpu;
typedef struct execute_args {
int ticks;
int quantum;
xcpu cs;
} eargs;
You have allocated an array of pointers in the line
eargs **targs = (eargs **) malloc(p * sizeof(eargs *));
but you haven't initialized the elements themselves. So this segfault has nothing to do with properly using memset on the fields of a struct, but instead derives from using uininitialized memory (assuming that you don't have a loop to initialize each eargs object after you allocate the array of pointers).
Instead, if you wanted to allocate a dynamic array of p eargs objects (I'm using the term "objects" loosely here), you would write
eargs *args = malloc(p * sizeof(eargs));
if (!args) {
/* Exit with an error message */
}
memset(&(args[i].cs), 0, sizeof(xcpu));
instead. Note that args is a dynamically allocated array of eargs objects, not a dynamically allocated array of pointers, so it's of type eargs * rather than eargs **.
Your memory allocation line doesn't allocate any memory for any structures, only for pointers to structures. If you want to allocate memory for that whole array, you need to add a loop to allocate memory for the structures themselves:
for (i = 0; i < p; i++)
targs[i] = malloc(sizeof(eargs));
Once you actually have structures to operate on, your memset() call should be fine.

size of a struct in c equals to 1

For some reason if I try to get the actual size of mystruct I keep getting size 1.
I know that mystruct is holding the data cause I can dump it out and everything is in mystruct.
What could be the reason of getting size 1?
Thanks
// fragments of my code
struct mystruct {
char *raw;
int count;
};
struct counter {
int total; // = 30
}
static struct mystruct **proc()
{
int i = 0;
gchar *key,*val;
struct mystruct **a_struct;
struct counter c;
a_struct = (struct mystruct **)malloc(sizeof(struct mystruct *)*c.total);
while (table (&iter, (gpointer) &key, (gpointer) &val)) {
a_struct[i] = (struct mystruct *)malloc(sizeof(struct mystruct));
a_struct[i]->raw = (char*)key;
a_struct[i++]->count = (int)val;
}
size_t l = sizeof(a_struct) / sizeof(struct mystruct*);
printf("%d",l); // outputs 1
}
You're doing a couple things wrong. First, you're taking sizeof(a_struct) which is going to be the size of a pointer (since that's what a_struct is) and then dividing by the size of another pointer. Guaranteed 1.
Besides that, why are you doing a division at all? What I think you want is:
size_t l = sizeof(struct mystruct);
or
size_t l = sizeof(**a_struct);
Edit:
I think I see the reason for your division now; you're trying to find the size of that array. That's not going to work - sizeof can only work at compile time in C (with some special exceptions in C99 which don't apply to your code), so it can't figure out the size of a dynamic array like that.
you're dividing the size of a pointer by the size of a pointer.
a_struct is a double pointer to struct mystruct.
struct mystruct * is a pointer to struct mystruct.
Both there sizes will be same.
Do this size_t l = sizeof(struct mystruct);
You are taking the size of two pointers and dividing one by the other,
size_t l = sizeof(a_struct) / sizeof(struct mystruct*);
a_struct is declared as struct mystruct **a_struct so this is the same as saying
size_t l = sizeof(struct mystruct **) / sizeof(struct mystruct*);
since all pointers have the same size, ** is the same size as *, so this will always evaluate to 1.
I'm not quite sure what you are trying to print out here, the size of a_struct ? or the total allocation size? The size of a_struct is just c.total, the total allocation is the sum of all of the values that you passed to malloc.

Resources