#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.
Related
For example I have a struct
struct s{
char c;
int x;
};
And I use calloc() to allocate memory.
s *sp = (s*) calloc(1, sizeof(s));
Now, what will be the values of sp->c and sp->x?
"What will be the values of sp->c and sp->x?"
Since calloc() sets all bits of the allocated memory to 0, c and x will have the value of 0 if the 0 value representation of int and char is of all bits to 0 (which is common).
Note that in the case of pointers, the pointer might not be standard-compliant NULL pointer when just setting all bits to 0 as the C standard does not require the representation of NULL pointers to be all-zero-bits.
Side notes:
1.
struct s{
char c;
int x;
};
s *sp = (s*) calloc(1, sizeof(s));
can´t work as s isn´t a typedefd type; it is a structure tag. Therefore, You need to precede s by the struct keyword:
struct s *sp = (struct s*) calloc(1, sizeof(struct s));
2.
You do not need to cast the returned pointer from calloc() and other memory management functions and rather avoid it since it can add clutter to your code. -> Do I cast the result of malloc
So, just do:
struct s *sp = calloc(1, sizeof(struct s));
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.
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);
Is this the correct way to allocate memory for a c struct that contains a dynamic array? In particular, is the way I allocate memory for myStruct correct, considering that it is not yet known how big the struct actually is?
//test.h
struct Test;
struct Test * testCreate();
void testDestroy(struct Test *);
void testSet(struct Test *, int);
//test.c
#include <stdlib.h>
struct Test{
double *var;
};
struct Test * testCreate(int size){
struct Test *myTest = (struct Test *) malloc(sizeof(struct Test));
myTest->var = malloc(sizeof(double)*size);
return(myTest);
}
void testDestroy(struct Test * myTest){
free(myTest->var);
free(myTest);
}
void testSet(struct Test * myTest, int size){
int i;
for (i=0;i<size;++i){
myTest->var[i] = i;
}
}
structs have fixed size, and that's what sizeof returns.
Your struct has on element, a double pointer, and that has a (platform dependent) fixed size.
Your testCreate function does things correctly. In case you don't know the size of the dynamically allocated part, you can set the pointer to NULL to denote that the memory has to be allocated later.
Yes, you correctly malloc space for the struct and then space for the array of doubles in the struct. As a practical matter, you should always test the return from malloc() for NULL before attempting to use the memory. Also, most programs like this store the size of the array in the struct as well so you can write more general code that ensures it doesn't run off the end of the allocated space.
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.