Can we dynamically allocate memory for structures? Is this a correct procedure to approach a dynamically allocated structures? Please tell me how to malloc() and realloc() a structure.
newnode is of type struct List * but when start indexing it converts to struct List.How this conversion possible?My insert function accepts only (struct List*) Am I wrong somewhere?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct List {
char val[20];
};
void insert(struct List *);
int main(void) {
int i = 0;
int size = 1;
struct List *newnode = (struct List *)malloc(size * sizeof(struct List));
for (i = 0; i < 5; i++) {
if (size <= i) {
size = size + size;
newnode = (struct List *)realloc(newnode, size * sizeof(struct List));
}
scanf("%s", newnode[i].val);
insert(newnode[i]);
}
for (i = 0; i < 5; i++) {
printf("%s\n", newnode[i].val);
}
return 0;
}
void insert(struct List *node) {
printf("%s\n", node->val);
}
The code works except for 3 problems:
You do not test for memory allocation failure. Both malloc() and realloc() will return NULL if memory cannot be allocated: you will get undefined behavior when dereferencing newnode should this happen.
to handle the case of realloc() failure gracefully, you should store the reallocated pointer to a different variable so you can still access the previous array that has not been deallocated and free it.
scanf("%s", newnode[i].val); is a security flaw: you should limit the number of bytes that can be stored to the destination array with
scanf("%19s", newnode[i].val);
you do not test the return value of scanf() to detect invalid or missing input.
insert() does not insert anything.
Here is a modified version with error handling and less confusing names:
#include <stdio.h>
#include <stdlib.h>
struct Item {
char val[20];
};
//void insert(struct Item *);
int main(void) {
int i, j;
int size = 0;
struct Item *array = NULL;
for (i = 0; i < 5; i++) {
if (i >= size) {
int newsize = size ? 1 : size + size;
struct Item *newarray = realloc(array, sizeof(*array) * size);
if (newarray == NULL) {
perror("cannot reallocate the array");
break;
}
size = newsize;
array = newarray;
}
if (scanf("%19s", array[i].val) != 1) {
fprintf(stderr, "missing input\n");
break;
}
//insert(array[i]);
}
for (j = 0; j < i; i++) {
printf("%s\n", array[i].val);
}
free(array);
return 0;
}
Yes, this is fine except that you are assigning the return value to your original array pointer. realloc() returns NULL if it can't resize the memory. You need to assign it to a temporary variable and, if the value is NULL, don't overwrite a.
The main thing you have to watch out for are pointers, which your struct doesn't have. In those cases, the memory pointed to is not part of the allocated array.
Related
Suppose we have some struct contains one member (An array). Memory is allocated for the struct according to the size of its members (Suppose 4 bytes).
Memory is also allocated for its member.
struct X {
int *arr;
};
int main() {
struct X *x = (struct X *)calloc(1, sizeof(struct X));
x->arr = (int *)calloc(5, sizeof(int));
}
Now, what happens to the struct if the memory block size allocated for arr is larger than the size allocated for the struct?
The structure contains just a pointer to int: when you allocate an object for an array of 5 int and set the arr member to point to this block, you have 2 allocated objects, one pointing to the other, no problem with that, but the programmer must keep track of the length of the allocated array somewhere.
As a matter of fact, if you add a length member to your structure, you will have an object where you can store a variable number of int values, an int_vector:
#include <stdio.h>
#include <stdlib.h>
struct int_vector {
int *arr;
size_t length;
};
struct int_vector *int_vector_alloc(size_t len) {
struct vector *v = calloc(1, sizeof(*v));
if (v) {
v->length = len;
v->arr = calloc(len, sizeof(*a->arr));
if (v->arr == NULL) {
free(v);
v = NULL;
}
}
return v;
}
void int_vector_free(struct int_vector *v) {
if (v) {
free(v->arr);
free(v);
}
}
void int_vector_print(const struct int_vector *v) {
if (v) {
const char *sep = "";
printf("[");
for (size_t i; i < v->length; i++) {
printf("%s%d", sep, v->arr[i]);
sep = ", ";
}
printf(" ]");
}
}
int main() {
struct int_vector *v = int_vector_alloc(5);
int_vector_print(v);
int_vector_free(v);
return 0;
}
I have a program that creates a struct named Stack that holds a pointer to an array of ints and an int that shows the size of this array.
I have functions to:
Initialize the struct with empty values
Push integers to the array (dynamically allocate more memory and write a value to it)
Pop an int from the array
However, when I try to pop the last element by freeing the memory it occupies, my program crashes.
What am I doing wrong here?
Is my process correct?
I realize the problem is probably that I'm trying to free a segment of memory that has not been allocated dynamically, but I just don't see where the issue is exactly.
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
struct Stack{
int *array;
int size;
};
typedef struct Stack Stack;
void initStack(Stack *stack);
void push(Stack *stack, int value);
int pop(Stack *stack);
int main()
{
Stack firstStack;
initStack(&firstStack);
push(&firstStack, 1222);
pop(&firstStack);
push(&firstStack, 555);
for(int i = 0; i < firstStack.size; ++i){
printf("#%d: %d (%p) ", i , firstStack.array[i], &firstStack.array[i]);
}
return 0;
}
void initStack(Stack *stack){
stack->array = NULL;
stack->size = 0;
}
void push(Stack *stack, int value){
int size = stack->size;
int newSize = size + 1;
stack->array = realloc(stack->array, newSize * sizeof(int));
if(stack->array != NULL){
stack->array[size] = value;
stack->size = stack->size + 1;
}
else{
printf("MALLOC ERROR");
}
}
int pop(Stack *stack){
int lastValue = stack->array[stack->size];
int lastIndex = (stack->size)-1;
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
stack->size = (stack->size) - 1 ;
printf("memory free\n");
return lastValue;
}
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
is wrong because lastAddress may not be an address allocated via malloc() family by adding lastIndex.
Remove the line
free(lastAddress);
If you want the system to change tha allocated size, you should change the line to
stack->array = realloc(stack->array, ((stack->size) - 1) * sizeof(int));
This is a problem:
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
The argument to free must be an address value returned from malloc, calloc, or realloc - you cannot free memory at an arbitrary address, even within a dynamically allocated block.
Some starters:
creating a dynamic array of a data structure called fractions.
Fractions has functions for setting, printing, intiting etc.
I kept getting an error for double freeing or corruption, along with a lot of gibberish from the memory map. This is the error from the output:
double free or corruption (top): 0x0000000001976010 *
I get that it is being freed/deleted twice but here is the code that generates the error:
#include <stdio.h>
#include <stdlib.h>
#include "fraction.h"
main() {
long long int size = 0;
long long int capacity = 10;
int FSize = sizeof(struct fraction);
struct fraction* array = NULL;
struct fraction in;
array = (struct fraction*)malloc(FSize * capacity);
if (array == NULL) {
printf("MALLOC DID NOT WORK\n");
exit(1);
}
int i = 0;
for (i = 0; i < 17; i++) {
if (size == capacity) {
capacity = capacity * 2;
struct fraction* temp = NULL;
temp = (struct fraction*)realloc(array, FSize * capacity);
// free(array);
array = temp;
free(temp);
}
SetFrac(&in);
array[size++] = in;
}
printf("IT MADE IT HERE >>>>>>>>>>>>>>>>>> \n");
getchar();
for (i = 0; i < size; i++) {
struct fraction t = array[i];
PrintFrac(&t);
}
free(array);
return 0;
}
Here is the code that works
#include <stdio.h>
#include <stdlib.h>
#include "fraction.h"
main() {
long long int size = 0;
long long int capacity = 10;
int FSize = sizeof(struct fraction);
struct fraction* array = NULL;
struct fraction in;
array = (struct fraction*)malloc(FSize * capacity);
if (array == NULL) {
printf("MALLOC DID NOT WORK\n");
exit(1);
}
int i = 0;
for (i = 0; i < 17; i++) {
if (size == capacity) {
capacity = capacity * 2;
struct fraction* temp = NULL;
temp = (struct fraction*)realloc(array, FSize * capacity);
// free(array);
array = temp;
free(temp);
}
SetFrac(&in);
array[size++] = in;
}
printf("IT MADE IT HERE >>>>>>>>>>>>>>>>>> \n");
getchar();
for (i = 0; i < size; i++) {
struct fraction t = array[i];
PrintFrac(&t);
}
// free(array);
return 0;
}
Am I using the free() function wrong?
array and temp have the same pointer address, so when you free temp, array will be freed also
You should only free "array" at the end. You must not free "temp", because you'll continue using the block (array = temp does not maintain a certain "reference count", but simply assigns a pointer).
After calling free, you should not dereference the freed memory, which you are doing by using array[size++].
You should not free() on temp there, because you are using array later.
Your final commented out free() would be the only one that would be correct, although the program should run fine with out it.
You don't need to free(temp) after realloc temp, just to free(array) the end of main. If you realloc is success,two possibilities:
temp == array (temp point to the same memory)
array is free and temp point to a new memory
I am trying to take input from console and add it to hash table.
But I'm getting Segmentation fault 11.
So, I debugged the program using gdb-apple.
It is showing that I'm trying access memory I cannot, using the pointer variable.
I think it is something obvious, but I'm missing it
This is what the gdb is displaying
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100000986 in CreateHashTable (size=200) at hashing.c:29
29 h->Table[i]->next = NULL;
Here is the code
Header File:
#define LOAD_FACTOR 20
#define INITIAL_SIZE 200
struct HashTable *CreateHashTable(int size);
int HashSearch(struct HashTable *h,int data);
int HashInsert(struct HashTable *h,int data);
int HashDelete(struct HashTable *h, int data);
void Rehash(struct HashTable *h);
int Hash(int data, int size);
struct ListNode
{
int key;
int data;
struct ListNode *next;
};
struct HashTableNode
{
int bcount;
struct ListNode *next;
};
struct HashTable
{
int tsize;
int count;
struct HashTableNode **Table;
};
Implementation file:
#include "hashing.h"
#include<stdio.h>
#include<stdlib.h>
struct HashTable *CreateHashTable(int size)
{
struct HashTable *h;
h = (struct HashTable *) malloc ( sizeof(struct HashTable) );
if(h == NULL)
{
printf("Memory Error");
return NULL;
}
h->tsize = (int) size/LOAD_FACTOR;
printf("h->tsize = %d",h->tsize);
h->count = 0;
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
if( h->Table == NULL )
{
printf("Memory Error");
return NULL;
}
int i;
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
return h;
}
I would paste the rest of file, or Driver file, but I don't see it relevant.
Please tell me why I'm getting the segmentation fault 11
You allocated memory for array of pointers but you didn't allocate memory for members of this array.
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i] = malloc(...); //put correct arguments here and check allocation
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
Your problem is here:
struct HashTableNode **Table;
You want an array of nodes (not a 2d array), change to:
struct HashTableNode *Table;
also change
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
to
h->Table = malloc(sizeof(struct HashTableNode) * h->tsize);
I think I want an array of pointers to nodes, don't I?
As pointed out by #WhozCraig, there is no reason for the additional level of indirection.
Example A (Pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *a; /* pointer */
int i, n = 10;
a = malloc(n * sizeof(int)); /* space for 10 ints */
for (i = 0; i < n; i++) {
a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", a[i]);
}
free(a);
return 0;
}
Example B (Pointer to pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int **a; /* pointer to pointer*/
int i, n = 10;
a = malloc(n * sizeof(int *)); /* space for 10 pointer to ints */
for (i = 0; i < n; i++) {
a[i] = malloc(sizeof(int)); /* space for 1 int */
*a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", *a[i]);
free(a[i]);
}
free(a);
return 0;
}
As you can see both do the same thing, but the first one requires less memory and the code is cleaner.
One way to make it easy to remember is:
int * can hold an array
int ** can hold a table (NROWS * NCOLS)
int *** can hold an array of tables
I wrote a piece of code to handle dynamic arrays. Idea was to use array of struct pointers, where the last member of array is NULL. Slight variation of code I wrote is below (using integers and not structures).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int **list, int* value) {
for(int i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
}
void list_init(int **list) {
int* x;
for(int i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(list, x);
}
}
int main() {
int** l = malloc(sizeof(int*));
l[0] = NULL;
list_init(l);
}
While debugging, I discovered that only first 3 integers are added to the list. I can't seem to figure out why is this happening. Any ideas?
The problem is that the call to realloc() in list_add() potentially frees the memory block *list and allocates another. list_add updates its list pointer, but it does not return the updated pointer to the caller, list_init(); list_init()'s list pointer is potentially a pointer to the recently-freed memory block.
To fix this code, list_add() and list_init() need to be able to "return" the updated list pointer:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int ***p_list, int *value) {
int **list = *p_list;
int i;
for(i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
*p_list = list;
}
void list_init(int ***p_list) {
int **list = *p_list;
int *x;
int i;
for(i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(&list, x);
}
*p_list = list;
}
int main() {
int **list = malloc(sizeof(int*));
list[0] = NULL;
list_init(&list);
int **l = list;
for (; *l != NULL; ++l) {
printf("%d\n", **l);
}
}
http://codepad.org/iGcSaJOR
EDIT
In this case of dynamic arrays the way you have told will not make anything better, the code will complicate only. For each addition of integer you have used realloc trying aggressively to save memory, but this will take more time while execution. Why not allocate a block of memory reserved for the array and to reflect the dynamic character put the array inside a struct with the last index, and when you add something add it on the last location and increment the counter. When this block is filled, you can chain another block to point to another one.
typedef struct _dyna_arr
{
my_type data_arr[MAX_LEN];
int n;
struct _dyna_arr *next block;
};
Therefore you maintain a linked list of multiple arrays. The size of MAX_LEN can be fixed which is appropriate for an application which will help decrease internal fragmentation.
*old answer removed *