Allocating more than what you need and freeing the extra space - c

I was wondering if it was possible to over allocate and free excess that you have allocated? I was thinking something along the lines of
/*
This is a pseudo program, just to show what I am talking about, there should be more
checks to prevent overflow.
*/
typedef struct {
struct Node *neighbor
int value
} Node;
...
Node create_tree(char* content, int size) {
int mem_index = 0
Node *last_node;
// size > sizeof(Node)
void base* = malloc(size);
while( mem_index < size) {
Node nptr* = (Node)(base + mem_index);
if(last_node != NULL) nptr->neighbor = last_node;
last_node = nptr;
mem_index += sizeof(Node);
nptr->value = (int)(base + mem_index)
(nptr->value)* = get_some_content(content);
mem_index += sizeof(int);
}
free((base + mem_index));
}
Basically this program over allocates and begins casting the memory into structures and then writes to those structures. It points the pointers within the structure to further points in the memory. It then writes another structure past all of that unit it is done with writing. I am wondering if this is possible, and if it is, is it good practice? I have heard under allocating is an issue, and I am not a fan of allocating every time I want to create a new structure if I am going to be creating them dynamically.

You can use realloc to shrink the memory block to the desired size:
base2 = realloc(base, mem_index);
If the call is successful, then the memory after base + mem_index will be freed.
BTW. Using pointer of type void* for arithmetic is GCC extension. You should use char*.
Note that returned base2 may not be same as the original base. You update all existing references to base with base2.

Related

Issue with pointer arithmetic in my own malloc() function

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.

How to perform deep copy using double poiners?

Question read.
In the below code, List used by Stack in-turn used by preOrderTraversal(), of rooted tree, without recursion but using explicit stack,
/* list.h */
typedef struct List{
void **array;
int lastItemPosition;
int size;
}List;
#define INITIAL_LIST_SIZE 50
List *createList(List *list, Op opType){
List *lptr = (List *)malloc(sizeof(List));
void *array = NULL;
if(opType == CREATE_NEW_LIST){
array = malloc(INITIAL_LIST_SIZE*sizeof(void*));
lptr->array = &array;
lptr->array = memset(lptr->array, 0, INITIAL_LIST_SIZE*sizeof(void *));
lptr->lastItemPosition = -1;
lptr->size = INITIAL_LIST_SIZE;
}else if(opType == DOUBLE_THE_LIST){
array = malloc(2*(list->size)*sizeof(void *));
lptr->array = &array;
lptr->array = memcpy(lptr->array, list->array, list->size*sizeof(void*));
lptr->lastItemPosition = list->lastItemPosition;;
lptr->size = 2*(list->size);
}else if(opType == HALF_THE_LIST){
array = malloc(((list->size)/2)*sizeof(void *));
lptr->array = &array;
lptr->array = memcpy(lptr->array, list->array, (list->size/2)*sizeof(void *));
lptr->lastItemPosition = list->lastItemPosition;;
lptr->size = (list->size)/2;
}
return lptr;
}
void insertItem(List *, void *, int);
void *deleteItem(List *, int);
List* createList(List *, Op);
/* Stack.h */
#include"list.h"
typedef struct Stack{
List *arrayList;
}Stack;
void push(void *);
void *pop();
void*top();
Wrt,
lptr->array = memcpy(lptr->array, list->array, list->size*sizeof(void*));
memcpy is passing double pointers. A double pointer is a single pointer to single pointer, so it can be passed to a function that expects a void pointer, But, the actual copy of array of void* should not work
As I actually need to copy the array of void*. if memcpy is called, like,
lptr->array = memcpy(*(lptr->array), *(list->array), list->size*sizeof(void*));
then,
Does memcpy perform copy operation, successfully? How to perform deep copy?
Your existing memcpy statement copies an array of void * values. Each of those void * presumably points to a different memory block, with some arbitrary contents. memcpy does not do anything with that arbitrary content: all you have done is to create a copy of the list of addresses of those blocks, not copied the blocks themselves.
It is hard to see how you can do anything at all with the underlying content, in the snippet of code that we can see here, and that includes copying it. This is because there is no record of the type or size of the content pointed-to by each void *'.
The suggestion you made:
memcpy(*(lptr->array), *(list->array), list->size*sizeof(void*))
will not work for several reasons. It asks memcpy to take the first void * value (not any of the others - that's one problem), and to look at the underlying memory block to which that first pointer points. It copies a certain amount of memory from the source to the destination block. But you have not mentioned allocating any new memory for the new destination block (thereby changing the value of the destination void * itself), so the source and destination are presumably the same address. That's another problem. Also, it uses the wrong size (size of the overall list of void *s, not the size of the memory block in question). That's yet another problem.
The goal you seem to want to achieve cannot be achieved with a single call. Your void *s may (as defined by code we cannot see here) point to consecutive parts of a single contiguous memory blockā€”in which case a single memcpy might appear to work "by accident". But as far as we know, they also might not be arranged like that. They might be separately-allocated chunks of memory all over the place. If so, you're going to need to treat each one separately: loop over the array of pointers, and for each one malloc new space for the copy of the associated block before copying that block. Of course, both to allocate and to copy, you're going to need to have a record of the size of each block.

Memory allocation of fixed size array inside a struct

I have the following tree node struct that holds pointers to other tree nodes:
struct node {
// ...
struct node* children[20];
}
The idea is that I want to check whether there is node* inside the children and based and that go deeper into the tree. So when I allocate the node I want to have children with 20 NULL values.
Currently I am not doin
How should I allocate this array in order to not get errors like Conditional jump or move depends on uninitialised value(s) (Valgrind)?
Would it be better to use struct node** children and allocate fixed size each time I allocate a new node?
EDIT: Example of one place where Valgrind complains:
for(int i=0;i<20;i++)
if(node->children[i] != NULL)
do_something_with_the_node(node->children[i]);
When you allocate a new instance of struct node, you must set the contained pointers to NULL to mark them as "not pointing anywhere". This will make the Valgrind warning go away, since the pointers will no longer be uninitialized.
Something like this:
struct node * node_new(void)
{
struct node *n = malloc(sizeof *n);
if(n != NULL)
{
for(size_t i = 0; i < sizeof n->children / sizeof *n->children; ++i)
n->children[i] = NULL;
}
return n;
}
You cannot portably use either memset() on n->children nor calloc(), since those will give you "all bits zero" which is not the same as "pointer NULL".
Your struct definition is valid (although it's hard to tell without more context if it fits your requirements).
Valgrind doesn't complain about your struct definition, it probably complains about how you instantiate variables of that type. Ensure that all of the array members get initialized and the complaints will most likely go away.
The problem is that you are using an unintialized value in an if condition.
When you instantiate a struct node, its member struct node* children[20]; is an array of 20 struct node *, all of which are uninitialized.
It would be no different from this:
char *x;
if (x == NULL) {
/* Stuff */
}
At this point, x may have literally any value. In your example, any element of an array may have any value.
To fix this, you need to initialize the elements of an array before using them, for example like this:
for (int i = 0; i < 20; ++i) {
node->children[i] = NULL;
}
Or shorter:
memset(node->children, 0, 20);
If you changed the member to, as you've suggested, node **children, the situation wouldn't be much different - you'll still need to initialize all the members, including array's elements. You could make it shorter by using calloc, which will initialize all bytes to 0; then again, you'll need some code for correct deallocation (and remember to do it), so I think the tradeoff's not worth it.

What are some useful examples of malloc() in C?

I'm just reading about malloc() in C.
The Wikipedia article provides an example, however it justs allocate enough memory for an array of 10 ints in comparison with int array[10]. Not very useful.
When would you decided to use malloc() over C handling the memory for you?
Dynamic data structures (lists, trees, etc.) use malloc to allocate their nodes on the heap. For example:
/* A singly-linked list node, holding data and pointer to next node */
struct slnode_t
{
struct slnode_t* next;
int data;
};
typedef struct slnode_t slnode;
/* Allocate a new node with the given data and next pointer */
slnode* sl_new_node(int data, slnode* next)
{
slnode* node = malloc(sizeof *node);
node->data = data;
node->next = next;
return node;
}
/* Insert the given data at the front of the list specified by a
** pointer to the head node
*/
void sl_insert_front(slnode** head, int data)
{
slnode* node = sl_new_node(data, *head);
*head = node;
}
Consider how new data is added to the list with sl_insert_front. You need to create a node that will hold the data and the pointer to the next node in the list. Where are you going to create it?
Maybe on the stack! - NO - where will that stack space be allocated? In which function? What happens to it when the function exits?
Maybe in static memory! - NO - you'll then have to know in advance how many list nodes you have because static memory is pre-allocated when the program loads.
On the heap? YES - because there you have all the required flexibility.
malloc is used in C to allocate stuff on the heap - memory space that can grow and shrink dynamically at runtime, and the ownership of which is completely under the programmer's control. There are many more examples where this is useful, but the one I'm showing here is a representative one. Eventually, in complex C programs you'll find that most of the program's data is on the heap, accessible through pointers. A correct program always knows which pointer "owns" the data and will carefully clean-up the allocated memory when it's no longer needed.
What if you don't know the size of the array when you write your program ?
As an example, we could imagine you want to load an image. At first you don't know its size, so you will have to read the size from the file, allocate a buffer with this size and then read the file in that buffer. Obviously you could not have use a static size array.
EDIT:
Another point is: When you use dynamic allocation, memory is allocated on the heap while arrays are allocated on the stack. This is quite important when you are programming on embedded device as stack can have a limited size compared to heap.
I recommend that you google Stack and Heap.
int* heapArray = (int*)malloc(10 * sizeof(int));
int stackArray[10];
Both are very similar in the way you access the data. They are very different in the way that the data is stored behind the scenes. The heapArray is allocated on the heap and is only deallocted when the application dies, or when free(heapArray) is called. The stackArray is allocated on the stack and is deallocated when the stack unwinds.
In the example you described int array[10] goes away when you leave your stack frame. If you would like the used memory to persist beyond local scope you have to use malloc();
Although you can do variable length arrays as of C99, there's still no decent substitute for the more dynamic data structures. A classic example is the linked list. To get an arbitrary size, you use malloc to allocate each node so that you can insert and delete without massive memory copying, as would be the case with a variable length array.
For example, an arbitrarily sized stack using a simple linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct sNode {
int payLoad;
struct sNode *next;
} tNode;
void stkPush (tNode **stk, int val) {
tNode *newNode = malloc (sizeof (tNode));
if (newNode == NULL) return;
newNode->payLoad = val;
newNode->next = *stk;
*stk = newNode;
}
int stkPop (tNode **stk) {
tNode *oldNode;
int val;
if (*stk == NULL) return 0;
oldNode = *stk;
*stk = oldNode->next;
val = oldNode->payLoad;
free (oldNode);
return val;
}
int main (void) {
tNode *top = NULL;
stkPush (&top, 42);
printf ("%d\n", stkPop (&top));
return 0;
}
Now, it's possible to do this with variable length arrays but, like writing an operating system in COBOL, there are better ways to do it.
malloc() is used whenever:
You need dynamic memory allocation
If you need to create array of size n, where n is calculated during your program execution, the only way you can do it is using malloc().
You need to allocate memory in heap
Variables defined in some functions live only till the end of this function. So, if some "callstack-independent" data is needed, it must be either passed/returned as function parameter (which is not always suitable), or stored in heap. The only way to store data in heap is to use malloc(). There are variable-size arrays, but they are allocated on stack.

Using malloc in C to allocate space for a typedef'd type

I'm not sure exactly what I need to use as an argument to malloc to allocate space in the table_allocate(int) function. I was thinking just count_table* cTable = malloc(sizeof(count_table*)), but that doesn't do anything with the size parameter. Am I supposed to allocate space for the list_node_t also? Below is what I am working with.
In the .h file I'm given this signature:
//create a count table struct and allocate space for it
//return it as a pointer
count_table_t* table_allocate(int);
Here are the structs that I'm supposed to use:
typedef struct list_node list_node_t;
struct list_node {
char *key;
int value;
//the next node in the list
list_node_t *next;
};
typedef struct count_table count_table_t;
struct count_table {
int size;
//an array of list_node pointers
list_node_t **list_array;
};
count_table* cTable = malloc(sizeof(count_table*))
is wrong. It should be
count_table* cTable = malloc(sizeof(count_table));
Also, you must allocate memory for list_node_t also seperately.
EDIT:
Apart from what Clifford has pointed about allocating memory for the list node, I think the memory allocation should also be taken care for the char *key inside of the list node.
Your suggestion: count_table* cTable = malloc(sizeof(count_table*)) would only allocate space for a pointer to a count_table.
You'd need
count_table* cTable = malloc(sizeof(count_table) ) ;
Each list node would be separately allocated and cTable->size and cTable->list_array and the last list_node_t::next updated accordingly. Maintaining a pointer to the last node added would make adding nodes faster.
I am not sure why count_table::list_array is of type list_node_t** rather than just list_node_t* (and equally called list_array rather than just list). Is it your intention that it is both an array and a list at the same time? That would be somewhat redundant. The member need only be a pointer to the first node, successive nodes are then accessed via list_node::next
Given that the int is a "size" parameter for the created count_table_t, it appears that you are supposed to both allocate the count_table_t itself, as well as initialise its members.
Initialising the list_array member also involves a memory allocation, so it would look like:
count_table_t *table_allocate(int size)
{
count_table_t *table = malloc(sizeof *table);
int i;
table->size = size;
table->list_array = malloc(size * sizeof table->list_array[0]);
for (i = 0; i < size; i++)
table->list_array[i] = NULL;
return table;
}
However, you also need to check for some error conditions: the multiplication of size by sizeof table->list_array[0] could overflow, and either of the malloc() calls could fail. So the function should actually look like this:
count_table_t *table_allocate(int size)
{
count_table_t *table;
int i;
/* Check for overflow in list allocation size */
if (size < 0 || size > (size_t)-1 / sizeof table->list_array[0])
return NULL;
table = malloc(sizeof *table);
if (table == NULL)
return NULL;
table->size = size;
table->list_array = malloc(size * sizeof table->list_array[0]);
if (table->list_array == NULL) {
free(table);
return NULL;
}
for (i = 0; i < size; i++)
table->list_array[i] = NULL;
return table;
}
(Note that (size_t)-1 is a constant equal to the maximum value of a size_t, which is the type of the parameter to malloc()).
In addition to the other posters who point out that you're only allocating enough space for the pointer, not the space the data you want will occupy, I strongly urge you to do things like this:
count_table* cTable = malloc(sizeof(*cTable));
This will help you in case the type of cTable ever changes, you won't have to adjust two parts to that line, just the type.

Resources