struct self referencing - c

I'm having syntax error everywhere, bad understanding of syntax for ADTs and memory handling. I need a struct that references to itself (other sections) in the next and prev. Am I doing it right? I get errors...
struct _header * header;
typedef struct _header {
int signiture;
int size;
header_t* next;
header_t* prev;
} header;
I also want to initialise the first 32 bytes within the memory with a header (this is not going well also..):
//this is to reference the memory block later
static int *free_list_ptr;
void function(u_int32_t size){
memory = (byte*) malloc(size);
header firstHead = malloc(sizeof(_header));
free_list_ptr = firstHead = memory;
firstHead->prev = free_list_ptr;
firstHead->next = free_list_ptr;
}

You can't reference a typedef while creating it, so you should do:
typedef struct a_header {
int signiture;
int size;
struct a_header* next;
struct a_header* prev;
} header;
header* the_header;
Avoid names with leading underscore - they are reserved for the system things.

Please try this:
typedef struct _header *lpheader;
typedef struct _header {
int signiture;
int size;
lpheader next;
lpheader prev;
} header, *lpheader;
Also why do you need 32 bytes worth of space for this structure? You should rather be using sizeof(_header).

You are thinking too complicated, your typedef is too late and you are using the wrong name inside the declaration of the struct.
typedef struct header header; // <- forward declare "struct header" and identifier "header"
struct header {
int signiture;
int size;
header* next;
header* prev;
};
For the sequel, I didn't really understand what you wanted to do. What is for sure that you use bizarre names in there that aren't declared and that you cast the return of malloc.

This is your current problem.
memory = (byte*) malloc(size);
header firstHead = malloc(sizeof(header));
free_list_ptr = firstHead = memory;
You allocate size and store its location as a byte* into memory.
Then you (correctly) allocate one header structure, and store that space's allocation into firstHead.
Then you throw that away (leaking that memory) by setting firstHead to the wrongly sized allocated space of memory, and then set free_list_ptr to the same wrongly sized allocated space.
Since your current pointer isn't holding enough memory, you get into trouble when you try to use the offsets of next and prev.
I suspect you need this:
memory = null;
header firstHead = malloc(sizeof(header));
memory = free_list_ptr = firstHead;
This will set the pointers memory and free_list_ptr to both point at the allocated space pointed at by firstHead.
I don't know why you are using two different pointers to track memory and free_list_ptr. My intuition is that 1 of these are probably sufficent for your purposes.

Related

Having trouble allocating memory for my double pointer in structure

I'm trying to allocate memory for a pointer, but have a reference to the address of that pointer. I'm still pretty new to C and this is my first time working with double pointers really.
So I have two structures and they look like this:
typedef struct myNodes {
int data;
struct myNodes *next;
} listElement;
typedef struct {
listElement **ptrToElements;
} myStruct;
In another file, I'm trying to dynamically allocate memory for my pointer by doing something like this:
myStruct *myStruct = malloc(sizeof(*myStruct));
*(myStruct->ptrToElements) = (listElement*)malloc(sizeof(listElement));
but I keep encountering a segmentation fault from doing so. What could be the issue? Thanks!
The problem is with
*(myStruct->ptrToElements) ....
statement. Before dereferencing myStruct->ptrToElements, you need to make sure it points to a valid memory.
To elaborate, you allocate memory for myStruct. Fine.
That constitutes allocating memory for the member ptrToElements. Good.
Question: What does ptrToElements points to?
Answer: Indeterministic.
So, when you try to derefernce a pointer which points to an indeterministic memory address, it's pretty much invalid memory address and attempt to do so will invoke undefined behavior.
Solution: You need to allocate memory for myStruct->ptrToElements before you can go ahead and dereference it.
having said that, please see do I cast the result of malloc?
You define the structure to contain a pointer to a pointer to a listElement
typedef struct {
listElement **ptrToElements;
} myStruct;
As Sourav Ghosh wrote, you try to assign a value to the pointer where ptrToElements would point to without allocating memory.
Probably you should change the pointer type to
typedef struct {
listElement *ptrToElements;
} myStruct;
and when allocating the memory
myStruct *myStruct = malloc(sizeof(*myStruct));
/* If the list can be empty, initialize root with NULL pointer */
myStruct->ptrToElements = NULL;
/* when you add the first list element */
myStruct->ptrToElements = malloc(sizeof(listElement));
myStruct->ptrToElements->data = someValue;
/* at least for the last element you add here you should initialize next */
myStruct->ptrToElements->next = NULL;
Don't forget to handle errors, e.g. malloc returning NULL.
I think this is what you want:
typedef struct myNodes {
int data;
struct myNodes *next; // not clear what this pointer is used for...
} listElement;
typedef struct {
listElement *ptrToElements;
} myStruct;
// Memory Allocation
// allocate myStruct pointing to an array of N listElements
myStruct *ms = malloc(sizeof(myStruct));
ms->ptrToElements = malloc(N * sizeof(listElement));
// element access
for (int i = 0; i < N; i++) {
listElement *le = ms->ptrToElements[i];
le->data = ...
le->next = NULL; // not clear what this pointer is used for...
}
// Memory deallocation
free(ms->ptrToElements);
free(ms);

Manually allocating memory for a struct

So I am working on a project in C where we need to implement malloc and free (meaning, we CANNOT use any C memory management functions such as malloc() or free()). This is only a code snippet, but it includes all relevant parts.
struct block_header
{
int size;
};
typedef struct FList_elem
{
struct block_header * header;
struct list_elem elem;
} FLelem;
void * manual_malloc(size_t size)
{
freeBlock = (FLelem *) mem_sbrk(newsize);
freeBlock->header = (struct block_header *) freeBlock;
freeBlock->header->size = newsize;
}
When allocating a new "block" of memory, we represent it via a structure FList_elem. In order to "allocate memory" for the struct, we point it at a memory address returned by mem_sbrk (works just like sbrk()). My question is, how do we establish memory for variables like size? Initially it's address is 0x0, and so assignments or references to it cause seg faults. Does it need to be a pointer so that we can set it's address, and then the value?
Instead of your original code, which stores a pointer to block_header inside the FList_elem structure, you can just embed the whole block_header structure inside the FList_elem structure:
struct block_header
{
int size;
};
typedef struct FList_elem
{
/* OLD code: struct block_header * header; */
/* Better code: block_header is embedded inside FList_elem structure */
struct block_header header;
struct list_elem elem;
} FLelem;
In this way, you don't need to allocate block_header separately: it's just there with the rest of FList_elem bytes.
And to set the size field (and any other attribute you may add to your block header) you can just do:
freeBlock->header.size = newsize;
When allocating the requested size, you need to add the header elements - and the pointer to the next block (eventually - the size can be computed with pointer difference as a space optimization... if this is embedded staff they are 4 bytes per block saved).
Since I think there are some incongruences, I have reported here my interpretation (not tested) of what you are trying to do:
struct block_header
{
int size;
};
typedef struct FList_elem
{
struct block_header header; // removed a * here: size is in place
struct Flist_elem *elem; // added a * here: that's the pointer to the next block.
} FLelem;
FLelem *memory_list = 0; // added a pointer for the global list - right?
void * manual_malloc(size_t newsize) // renamed as newsize here
{
freeBlock = (FLelem *) mem_sbrk(newsize + sizeof(FLelem));
freeBlock->header.size = newsize;
freeBlock->header.elem = memory_list;
memory_list = freeBlock;
// inserted freeBlock at the head of memory_list;
return (void*)(freeBlock+1); // +1 to skip the header as a return address
}
The caller of the function will have returned the space after the header.
Your manual_free() function will take as an argument this returned memory pointer, and it will need to subtract and go back a freeblock in memory in order to find the header and to release the block, and than you will need some sort of tree (bit tree) to keep of track of the holes left free... If you need to handle dynamic memory - and that's where it start being interesting.
Hope I have not done errors and that it's clear enough!
#include <stdlib.h>
struct st *x = malloc(sizeof *x);
Note that:
x must be a pointer
no cast is required
include appropriate header

seg fault after trying to access ladder part of sbrk free space

Ok, so I have a struct that looks like
typedef struct meta {
size_t size;
struct meta* next;
struct meta* prev;
} meta_t;
I also statically allocate the beginning list pointer and the end list pointer as:
static meta_t* freelist_b = NULL;
static meta_t* freelist_e = NULL;
I then free a block of 4 MB of space and set the beginning list pointer to it
size_t max_bytes = ALIGN(1024*1024*4);
freelist_b = (meta_t*) sbrk(max_bytes);
Then I try to do the same for the end of list pointer
freelist_e = memcpy(freelist_b+max_bytes-sizeof(meta_t),freelist_b,sizeof(meta_t));
But this line gives a segmentation fault. Can anyone tell me what I'm doing wrong or how to further debug this? Thanks.
When you do freelist_b+max_bytes-sizeof(meta_t), you are using operator+ on a pointer to a meta_t structure. This adds a lot more than what you probably expect.
Change:
freelist_b
To:
(char*)freelist_b
Or change:
max_bytes-sizeof(meta_t)
To:
max_bytes/sizeof(meta_t)-1

whats wrong in this program?

Am unable to run this code...
#include<cstdio>
int main()
{
struct a{
int b;
struct a *next;
};
typedef struct a no;
no *n;
n->b = 12;
n->next = NULL;
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
return 0;
}
When you say:
no *n;
you get an uninitialised pointer. When you use that pointer, you get undefined behaviour.
You allocated space for a pointer to a structure, but you didn't allocate space for the actual structure. This means that you don't have a memory address for the structure you are using.
In addition, the pointer points to some random memory address because you didn't initialize it. As a result, you could be trying to read and write to memory that doesn't belong to you, which can cause your program or even your system to crash because of the undefined behavior that results.
As #Neil Butterworth said, you get an uninitialised pointer. This mean that this pointer could point to anywhere, thus giving an access violation error. The way to fix this is simple, just call malloc() before using that pointer. malloc() gives that pointer a valid and usable address, so no one will complain about that.
You're declaring a struct INSIDE a function.
Declare the struct OUTSIDE of the function.
The typedef should be declared outside the function too.
#include<cstdio>
struct a{
int b;
struct a *next;
};
typedef struct a no;
int main()
{
///... your code...
}
try something like this:
no *n = (no*)malloc(sizeof(no));
#include <cstdio>
/* declaring the struct in the function definition may be possible (I'm not sure,
actually, haha). Unless you have a GOOD reason, it's good practice to declare
structs, globals, typedefs, etc... outside the function */
typedef struct a{
int b;
struct a *next;
} no;
int main()
{
no *n;
/* Here, you have a pointer. Remember these are simply (generally) 32-bit values
defined in your stack space used to store a memory location which points to your
ACTUAL struct a! Depending on what USED to be in the stack space, this could
point ANYWHERE in memory, but usually you will find that it points to the NULL
memory location, which is just address "0". To get this to point to something,
you have to allocate empty space on your heap to store your struct... */
n = malloc(sizeof(no));
/* Now your pointer n points to an allocated 'struct a', and you can use it like
normal */
n->b = 12;
n->next = NULL;
/* You just set n->next, which is another 'no' pointer, to NULL. This means that
n->next points nowhere. So, just like above you have to malloc another instance
of the struct! */
n->next = malloc(sizeof(no));
/* NOW you can use n->next with no ill effects! */
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
/* After you're done with your structs, you want to free them using the POINTERS
that reference them */
free(n->next);
free(n);
return 0;
}

Why this code doesn't allocate memory in C?

Updated question is here
Memory allocation problem in HashTable
I'm working on making a HashTable in C. This is what I've done. I think I'm going on a right path but when I'm trying to
main.c
HashTablePtr hash;
hash = createHashTable(10);
insert(hash, "hello");
insert(hash, "world");
HashTable.c
HashTablePtr createHashTable(unsigned int capacity){
HashTablePtr hash;
hash = (HashTablePtr) malloc(sizeof(HashTablePtr));
hash->size = 0;
hash->capacity = capacity;
ListPtr mylist = (ListPtr)calloc(capacity, sizeof(ListPtr)); /* WHY IT DOESN'T ALLOCATE MEMORY FOR mylist HERE?? */
mylist->head = NULL;
mylist->size = 0;
mylist->tail = NULL;
hash->list = mylist;
return hash;
ListPtr is a LinkedList ptr
List.h
typedef struct list List;
typedef struct list * ListPtr;
struct list {
int size;
NodePtr head;
NodePtr tail;
};
...
...
HashTable.h
typedef struct hashtable * HashTablePtr;
typedef struct hashtable HashTable;
struct hashtable {
unsigned int capacity;
unsigned int size;
ListPtr *list;
unsigned int (*makeHash)(unsigned int, void *);
};
...
...
When I run my debugger, I see no memory being allocated to myList. In above example, my attempt is to make it an array of 10 lists.
Please help me to solve this.
I'm not that expert in C, if that helps.
calloc(capacity, sizeof(ListPtr)
should be
calloc(capacity, sizeof(List)
I think there are a whole host of problems here. You haven't included the error you getting so, I will list a couple:
hash = (HashTablePtr) malloc(sizeof(HashTablePtr*)); - You are allocating the size of a HashTable **, which is four bytes, you need to allocate the size of the underlying object.
ListPtr mylist = (ListPtr* )calloc(capacity, sizeof(ListPtr)); - Again, your are allocating the size of the pointer rather than the underlying list object.
HashTablePtr createHashTable(unsigned int capacity)){ - You are probably getting a compile error here with the extra parens and the inconsistent number of parameters.
Personally I am not a huge fan of using typedefs, especially when you are a beginner. I think that may be partially what is confusing you. You are better avoiding things like:
typedef struct hashtable * HashTablePtr;
Using to many typedefs will make your code harder to read since you will need to constantly look up what they are referring too.
The main problem is that you were allocating the memory for the size of a hashtable/list pointer and not for the size of their respected structures. I think the code below shows this well. You will also want to check if you allocations worked. If malloc, calloc, realloc. etc. fail they return NULL. If this happens and you do not check for this case you will get a segfault error and your program will crash.
Also follow the c99 standard, and put all of your variable declarations at the start of the function.
c99 std
malloc manpage
struct hashtable *
createHashTable(unsigned int capacity){
struct hashtable *hash;
struct list *mylist;
/* You want to allocate size of the hash structure not the size of a pointer. */
hash = malloc(sizeof(struct hashtable));
// always make sure if the allocation worked.
if(hash == NULL){
fprintf(stderr, "Could not allocate hashtable\n");
return NULL;
}
hash->size = 0;
hash->capacity = capacity;
/* Unless you need the memory to be zero'd I would just use malloc here
* mylist = calloc(capacity, sizeof(struct list)); */
mylist = malloc(capacity * sizeof(struct list));
if(mylist == NULL){
fprintf(stderr, "Could not allocate list\n");
free(hash); /* free our memory and handle the error*/
return NULL;
}
mylist->head = NULL;
mylist->size = 0;
mylist->tail = NULL;
hash->list = mylist;
return hash;
}
Also remember to free you list before you free your hashtable:
free(myhash->list);
free(myhash);
You are allocating a contigous block of ListPtr's, but you actually want to allocate space for the all the structures rather than just pointers (ListPtr) to those structures:
calloc(capacity, sizeof(List));
I agree with gman's comment about not hiding pointers. When coding in C, I never typdef a List * as a ListPtr. It makes the code harder to understand.

Resources