Having trouble with my task here. I need to create a global block of free memory and malloc it. Having some trouble initialising it due to typecast and handling errors.
Like arrays in C where the first array is actually a pointer to the first element, my memory block needs to be similar where i can use pointer arithmetic to locate blocks of memory.
//global variable
static byte *memory = NULL;
void allocator_init(u_int32_t size){
*memory = (byte*) malloc(size);
}
The addresses/pointers to these memory addresses will be stored via structs/links as headers of the memory block.
typedef struct _header {
int signiture;
int size;
header* next;
header* prev;
} header;
Drop the *:
*memory = (byte*) malloc(size);
^
You might also want to drop the cast but that's your call.
You need to assign the return value of malloc to the pointer itself, not to the byte pointed to by the pointer. (Anyway, if you dereference the initially NULL pointer, your program will segfault.)
memory = malloc(size);
Also, don't caat the return value of malloc.
*memory = (byte*) malloc(size); - This statement means you are trying to assign the address of the heap memory block as a value to *memory. Here memory is having NULL, so it will crash.
You have to assign the addres to the variable like, memory = (byte*) malloc(size);
In your header struct, since the struct references itself, declare the internal header pointers as "struct _header * name;". I think other people have hit all the other points :)
Related
I am currently working on implementing my own malloc() function. The one thing that seems to not be working is that I'm unable to correctly return the memory address of the beginning of my current block. My block struct looks like this and is of size 16:
typedef struct block {
size_t size;
struct block* next;
struct block* prev;
int free;
} block_t;
My malloc looks like this currently:
void *bmalloc(size_t size)
{
void * mem=0;
size_t alloc=size;
if (freelist==0)
{
freelist=&heap[0];
freelist->free=0;
freelist->prev=0;
freelist->size=MAX_HEAP_SIZE;
freelist->next=0;
//printf("is this happening?");
}
for (curr=freelist;curr!=NULL;curr=curr->next)
{
if (alloc<=curr->size && curr->free==0)
{
block_t *tmp=curr->next;
curr->free=1;
curr>size=MAX_HEAP_SIZE;
curr>next=curr+alloc+sizeof(block_t);
//curr->next->next=tmp;
curr->next->size=curr->size-alloc;
curr->next->free=0;
curr->next->prev=curr;
mem=curr+sizeof(block_t)
return mem;
}
}
}
Curr and Freelist are both block_t structs. I know the issue must lie in the step where I set mem=curr+sizeof(block_t), but I'm not really sure how to fix it. Upon some checking I noticed that the first allocation of memory returns an address 276 bytes away from the beginning of the array the blocks live on top of, and after the first allocation the blocks memory addresses are 512 bytes away.
Whenever you do pointer arithmetic, the values are always scaled by the size of the type the pointer points at. So when you do
mem = cur + sizeof(block_t);
since cur is a block_t *, the addition is scaled by sizeof(block_t) automatically. Which means that if sizeof(block_t) is 16, this will add 256 bytes to the pointer, which is not what you want. You probably just want
mem = cur + 1;
here, and similar changes elsewhere.
I have come across an instance where memory is allocated dynamically to a char pointer within a struct in a way that does not make much sense to me, but - of course - works.
A similar question has been posted before. The answers, however, did not help me understand what is actually happening in the allocation process.
Here is the code example I found:
struct a_structure {
char *str;
struct a_structure *next;
};
Memory has been allocated in the following way:
ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
...
char *some_words="How does this work?";
ptr_start->str=(char *)malloc(strlen(some_words)+1);
strcpy(ptr_start->str, some_words);
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
...
I don't understand why malloc is used with the size of a pointer here. ptr_start is a pointer of type struct a_structure. That would mean it needs memory of size sizeof(struct a_structure) + the size of my string that hasn't been specified in the structure declaration. In the above example, however, malloc returns the address of yet another pointer pointing to a structure of type a_structure, am I right?
I don't understand why malloc is used with the size of a pointer here.
ptr_start is a pointer of type struct a_structure. That would mean it
needs memory of size sizeof(struct a_structure) + the size of my
string that hasn't been specified in the structure declaration
You are right. To create structure a_structure in order to manipulate it we need to allocate memory for whole structure.
(Unless the object has been ALREADY created and for whatever reason we need a dynamically allocated pointer holding pointer to that object).
but - of course - works.
The presented fragment of the program cannot work properly for the stated above reasons.
In the above example, however, malloc returns the address of yet
another pointer pointing to a structure of type a_structure, am I
right?
Yes, you are right.
This is also problematic:
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
ptr_start->next can hold a pointer already. We typically do not need to allocate a pointer here. We would assign a pointer to the existing
structure or we would allocate memory for the whole structure.
See example:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct a_structure {
char *str;
struct a_structure *next;
};
struct a_structure * allocatePointer(void)
{
// ptr ptrToObj1Allocated points to allocted memory which can hold a ponter
struct a_structure * ptrToObj1Allocated = malloc(sizeof (struct a_structure *));
return ptrToObj1Allocated;
}
int main(){
// 1.
struct a_structure obj1; // structure a_structure has been allocated on the stack
struct a_structure * ptrToObj1 = & obj1; // points to the existing structure
char *some_words = "How does this work?";
ptrToObj1->str = malloc(strlen(some_words)+1);
if(ptrToObj1->str == NULL){printf("No enough memory\n"); return -1;}
strcpy(ptrToObj1->str, some_words); // copy the string
// now obj1 has its own copy of the string.
// 2.
// dynamically allocate another structure on the heap
// we want to allocate memory for the structure not just a memory to keep the pointer to the structure.
struct a_structure *obj2 = malloc( sizeof (struct a_structure)); // memory has been allocated to hold struct a_structure with 2 pointers
if(obj2 == NULL){printf("No enough memory\n"); return -2;}
char *words = "More words..";
obj2->str = malloc(strlen(words)+1);
if(obj2->str == NULL){printf("No enough memory\n"); return -3;}
strcpy(obj2->str, words); // copy the string
obj2->next = ptrToObj1; // points to the already existing object
//----
printf("String in obj1 is: %s\n", ptrToObj1->str);
printf("String in obj2 is: %s\n", obj2->str);
printf("obj2->next points to structure with string: %s\n", obj2->next->str );
// free the allocated memory:
free(ptrToObj1->str);
free(obj2->str);
free(obj2);
return 0;
}
Output:
String in obj1 is: How does this work?
String in obj2 is: More words..
obj2->next points to structure with string: How does this work?
Given that you have struct a_structure* ptr_start, this code is incorrect and does not work:
ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
It should have been:
ptr_start = malloc(sizeof *ptr_start);
The reason why it "seems to work" is because you invoked undefined behavior, and anything can happen. The program could seem to work one moment, then crash at another time.
This does however just allocate the struct itself. The pointers inside it will, like all pointers, point at memory allocated somewhere else. The following code with malloc for the string and strcpy() is one way to do so.
The last line is however incorrect for the same reason as pointed out above.
This is my code:-
typedef struct Frame
{
char* name;
unsigned int duration;
char* path; // may need to scan (with fgets)
}frame_t;
typedef struct Link
{
frame_t* frame;
struct Link* next;
}link_t;
void addNewFrame(void)
{
link_t* newLink = (link_t**)malloc(sizeof(link_t*));
printf(" *** Creating new frame ***\n\n");
printf("Please insert frame path:\n");
// newLink->frame->name = (char*)malloc(sizeof(char) * MAX_LEN);
fgets(newLink->frame->name, MAX_LEN,stdin);
printf("%s", newLink->frame->name);
}
I just need to add a data to name variable in the "Frame" link list, please help me by reviewing this code.
You want to allocate the right types here:-
link_t* newLink = malloc(sizeof(link_t)); //Pointer to Link st
if(newLink){
newLink->frame = malloc(sizeof(frame_t)); //Pointer to frame member
if(newLink->frame){
newLink->frame->name = malloc(sizeof(char) * MAX_LEN); //Pointer to name member
if(newLink->frame->name){
//Rest of your code
}
}
}
EDIT:-
1. As pointed out in comments there's no need to cast the pointer returned by malloc()
2. Another very imp point you may want to check validity of the pointers before de-referencing them
First. You don't need to cast void * so (link_t **)malloc(... can be only malloc(....
Second. You allocated enough memory for a pointer not for a struct. I think you mean malloc(sizeof(link_t)) or even better malloc(sizeof(*newLink))
Third newLink->frame is a pointer so you need to allocate data for it too, newLink->frame = malloc(sizeof(frame_t))
Fourth newLink->frame->name is still a pointer so you need to allocate data for it too. newLink->frame->name = malloc(MAX_LEN)
The confusion that you are doing is pretty common. When you say type *something you are allocating a pointer to type in the stack. A pointer needs to point to somewhere else or NULL, or bad things happen. This applies to structures too. If your structure has a pointer member you need to point it to somewhere else. The somewhere else is where the real "type" object resides.
This also applies to arrays. If you say 'int foo[10]' you are allocating ten integers in the stack. If you say int *foo[10] you are allocating ten pointers in the stack. If you say int **foo you are allocating one pointer in the stack. Again all pointers need to be initialized, I mean, they need to point to some valid object, allocated somewhere else in the memory.
I hope this helps.
Some other points.
Always check pointer coming from malloc, if allocation failed you'll receive NULL. Dereferencing NULL will break your program.
Always initialize memory coming from malloc, fill it with zeros or something.
Don't use _t suffix, is POSIX reserved.
I didn't test any of this.
I have a struct which contains 2 integers and a pointer to another struct. I allocate memory for struct first and then for the pointer. When I free the memory I free up the pointer first and then I free up the struct.
When I run my program and call the function that frees memory it crashes when the call is made. When I don't call the function that frees memory it works fine, but then I'm not freeing up the memory.
I tried removing the line that frees the memory allocated to the pointer and the program doesn't crash, but I don't think thats right since a "free" is needed for every "malloc/calloc" right? Anyone see anything wrong with the freeing function?
//Define a struct data type
struct q_element
{
//Declaration of struct members
int element;
int priority;
struct q_element *next_element;
};
//Method to allocate memory
struct q_element* allocateStruct()
{
//Declaration of a variable
struct q_element *e;
//Allocate memory for one queue element
e = malloc(sizeof(struct q_element));
//Allocate memory for one pointer to a queue element
e->next_element = calloc(1,sizeof(struct q_element*));
//Initialize integer members of queue element
e->element = 0;
e->priority = 0;
return e;
}
//Method to free memory allocated
void freeStruct(struct q_element* e)
{
//Free up pointer member
free(e->next_element);
//Free up struct
free(e);
}
You don't need to allocate memory for the next_element pointer. The pointer is already there, just like int element for example.
So if you want to allocate just one element, you can set the next_element pointer to NULL and everything is fine.
You are not allocating enough memory for e->next_element in the line:
e->next_element = calloc(1,sizeof(struct q_element*));
// ^^^ remove the *
That should be:
e->next_element = calloc(1,sizeof(struct q_element));
If you used e->next_element as though it were a valid pointer, you most likely ended up accessing memory that you did not allocate. That clobbered some of the bookkeeping information created by calloc, which lead to problems when you called free.
In
//Allocate memory for one pointer to a queue element
e->next_element = calloc(1,sizeof(struct q_element*));
you allocate space for a pointer to a q_element structure, rather than a q_element structure. Do you attempt to write to this structure, because if so, that's probably where it goes wrong.
As a side note you might be better off just doing
e->next_element = 0
inside allocate_struct and then doing e->next_element = allocate_struct() outside the function later.
In addition to what everyone else is mentioning about allocation, you also need a sentinel to check if the next_element was already freed. You may be attempting a double free.
Try the following code:
void freeStruct(struct q_element* e)
{
//Free up pointer member
if(e->next_element != 0){
free(e->next_element);
e->next_element = 0;
}
//Free up struct
free(e);
}
beginner in C here. Is this legal here? I keep getting status access violation when i run this code:
struct point {
char *x;
char *y;
}
int main()
{
....
struct point *pt;
for (;;)
{
....
pt = process_message(message);
printf("%s",pt->x);
...
}
}
struct point* process_message(char* message)
{
struct point *pt;
pt = malloc(1*sizeof(struct point))
strncpy(pt->x, message, 4);
return pt;
}
EDIT
Hi guys i made some changes...but still getting the access violation. pls advise!
You need to allocate memory for struct point in process_message.
Something like this:
struct point* process_message(char* message)
{
struct point *pt;
pt = malloc(1*sizeof(struct point));
// ... do some processing ...
return pt;
}
Of course, you should free the pointer at some point afterwards.
Also you should return a struct point in process_message or check your type concordance. If you look carefully, you will see you are returning a struct price* but you are expecting (on the calling side) a struct point *.
UPDATE:
Now that question was updated, you will also need to allocate memory for char *x and char *y if you want to do this:
strncpy(pt->x, message, 4);
I would recommend to read a little bit (or a lot) about memory management and pointers in C++. Pointers are not the only way of dealing with data in C Programming Language.
(NO ERROR CHECKING DONE FOR CODE SIMPLICITY)
Your main function is OK. Your problem is in process_message, where you're using a pointer-to-a-struct but not allocating any memory for it, accessing it, then returning it. Declaring a pointer alone does not create the memory to hold the struct. So you should allocate (use malloc for example) the memory for the struct, so that the memory will "exist" after the end of the function. Then you can return the pointer to it as you're doing, and then you would free it in main when you were done with it.
There are possibly better ways to accomplish the goal here given the simple operation you're doing. One is to keep one "scratch" struct local in your main function, and pass its address to process message:
struct point pt;
process_message(message, &pt);
printf("%s", pt.x);
This will "Reuse" the local memory and not require the alloc/free. Notice here that you don't return anything, you just "fill in" the struct in the process function.
Finally, if you're using a modern version of C, you can actually just return the full structure from the function if you want:
struct point process_message(char* message)
{
struct point pt;
... do some processing ...
return pt;
}
And call it like this:
struct point pt = process_message(message);
Remember to allocate memory in the function process_message
pt = malloc (sizeof (struct point));
/* do processing */
return pt;
also after you have finished working with pt remember to free it free (pt).
EDIT
Also you need to allocate the memory blocks to store the strings to x and y in the function, after allocation of the pt. When you have done working, you need to free the strings first (memory blocks) and then the structure.
Whenever you create pointer, it's just a sizeof(ptr) memory , which points to some data. So you must have some memory where your data is stored.
So either allocate memory in your function ( process_message), or in calling function.
it should go like
struct point *pt = (struct point*)malloc(sizeof(struct point));
As written now, you're allocating the struct point, but that structure contains pointers to strings, and not storage for the strings themselves. You need to allocate space for the strings before you copy into them:
pt = malloc(1*sizeof(struct point));
pt->x = (char *)malloc( strlen(message) + 1);
Don't forget to do the same for pt->y before you use it, and don't forget to separately free the storage allocated for the strings, and then that allocated for the struct.