C dynamic array problem - c

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 *

Related

malloc() and realloc() of structures

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.

Singly linked list create function C

I am currently trying to make function create() for singly linked list, where I am supposed to pass unlimited amount of parameters and it will pass the parameters as nodes' values. The code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//define sllnode struct
typedef struct sllist
{
int val;
struct sllist *next;
}
sllnode;
sllnode* create(int count, ...);
int main(void)
{
//here i try to print out values of this list
sllnode* new_sllist = create(34,2,5,18);
//print out values that I have assign using create() to test
for(int i = 0; i < 4; i++)
{
printf("%i\n",new_sllist[i].val);
}
}
//create function
sllnode* create(int count, ...)
{
va_list list;
int i;
int arr[count];
va_start(list, count);
//create array arr that have all the values passed as parameters
for(i = 0; i < count; i++)
{
arr[i] = va_arg(list,int);
}
//allocate memory for new singly linked list
sllnode *sllist = malloc(count * sizeof(sllnode));
//check if memory has been successfully allocated
if(sllist == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
// loop through array arr and assign values to val and *next of each sllnode in new sllist
for (int j = 0; j < count; j++)
{
sllist[j].val = arr[j];
sllist[j].next = &sllist[j+1];
if(j == count - 1)
{
sllist[j].val = arr[j];
sllist[j].next = NULL;
}
}
return sllist;
free(sllist);
}
But when I print out I only receive the last 3 values (2,5,18) and a number -23791193490 which differs each time (I suppose this has seeped into another part of memory). How do I do this correctly?
You are passing 34 for the count parameter. Correct usage would be:
sllnode* new_sllist = create(4,34,2,5,18);

Malloc large space of struct and accessing it like arrays in c

I'm dealing with implementing a hash table. My understanding of a hashtable is that is that to have an array like table where you're able to access the elements quickly by getting the hash value and modding it by the table size. So my initial thought was declaring
Node *hTable [100];
where
typedef struct node {
char *s;
int value;
} Node;
and going to the index of the array and malloc a new element that belongs there. But, the problem is that I need to grow my table.
So, my question is, how would I make a dynamic table, but access it like an array? (e.g table[i]).
I know that you need to call something like
Node *table = (Node*)malloc(sizeof(Node)*size);
which lets you access it like a table table[i] =... but if I did that, I can't declare a new Node in the index of the table
table[i]=(Node*)malloc(sizeof(Node));
Here's a code that I've been testing with (getting seg fault) to better give a view of the problem:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef struct node {
5 int data;
6 struct node *next;
7 } Node;
8
9
10 void main() {
11 Node **list;
12 *list = (Node*)malloc(sizeof(Node)*10);
13 for (int i = 0; i < 10; i++) {
14 list[i] = (Node*)malloc(sizeof(Node)); //problem here?
15 list[i]->data = i;
16 list[i]->next = NULL;
17 }
18 printf("printing...\n");
19 for (int i = 0; i < 10; i++) {
20 printf("%d ", list[i]->data);
21 }
22 }
Your problem is how you allocate space for list. list is uninitialized and does not point to valid memory, you must allocate space for it first, and then allocate space for each element:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} Node;
int main() //return type of main is int
{
Node **list;
list = malloc(10 * sizeof *list); //allocate memory for list not *list, also no need to cast return value of malloc.
for (int i = 0; i < 10; i++)
{
list[i] = malloc(sizeof *list[i]); //allocate space for each element.
list[i]->data = i;
list[i]->next = NULL;
}
printf("printing...\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", list[i]->data);
}
return 0;
}
It doesn't need to be an array of pointers, you can simply make an array of nodes, with:
Node *list = malloc(sizeof *list * count);
Then you can access list[i].s and list[i].value.
When you want to grow the table, you use realloc():
new_list = realloc(list, sizeof *list * new_count);
if (new_list) {
list = new_list;
} else {
// report allocation failure
}
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
int main() {
// just initialize it this way ( previous was undefined behavior, dereferencing an initialize pointer)
Node **list= malloc(sizeof(Node*)*10);
for (int i = 0; i < 10; i++) {
list[i] = malloc(sizeof(Node*)); //problem here?
list[i]->data = i;
list[i]->next = NULL;
}
printf("printing...\n");
for (int i = 0; i < 10; i++) {
printf("%d ", list[i]->data);
}
}

C double freeing error

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

segmentation fault 11, while pointer variables

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

Resources