I'm trying to understand how does dynamic memory allocation in C work. So I coded this:
typedef struct person{
int id;
int credit;
}person_t;
typedef struct list{
int id;
person_t * people;
}list_t;
int main(){
list_t * list;
list = malloc(sizeof(list_t));
list->people = malloc(10 * sizeof(person_t)); //list for 10 people
free(list->people);
free(list);
}
, which appears to be correct. However, when I decided to create functions for allocation\deallocation, double free or corruption error started to appear:
void init_list(list_t * listptr, int size){
listptr = malloc(sizeof(list_t));
listptr->people = malloc(size * sizeof(person_t));
}
void clear_list(list_t * listptr){
free(listptr->people);
free(listptr);
}
int main(){
list_t list;
init_list(&list, 10); //list for 10 people
clear_list(&list);
}
Output:
Error in ./list: double free or corruption (out) : 0x00007ffc1b3fba70
Why could that be? Thanks in advance.
void init_list(list_t * listptr, int size){
listptr = malloc(sizeof(list_t));
listptr->people = malloc(size * sizeof(person_t));
}
is not correct. You are modifying listptr in the function. That does not change anything of list in main. You need to remove the line fhat changes listptr in that function. Use:
// listptr is already a valid pointer.
// There is no need to allocate memory for it.
void init_list(list_t * listptr, int size){
listptr->people = malloc(size * sizeof(person_t));
}
You have a worse mistake in clear_list.
void clear_list(list_t * listptr){
free(listptr->people);
free(listptr);
}
You are calling free on a pointer that was not allocated by a call to malloc. listptr is a pointer to the object that was created in stack in main. Remove the second call to free. Use:
// listptr is a pointer to an object on the stack in main.
// Trying to call free on it is an error.
void clear_list(list_t * listptr){
free(listptr->people);
}
Related
struct DynamicArray {
int allocated;
int used;
int *array;
}; typedef struct DynamicArray DynamicArray;
DynamicArray * ArrayCreate(int initialSize) {
DynamicArray *array;
(*array).array = (int*)malloc(initialSize*sizeof(int)); //Debugger points this line.
if((*array).array == NULL) {
return NULL;
}
(*array).allocated = initialSize;
(*array).used=0;
return array;
}
I am trying to make my own library for dynamic arrays. Just to learn and improve myself. Please review my code. What am I doing wrong?
You are de-referencing an uninitialized pointer here:
DynamicArray *array; // uninitialized
(*array).array = .... // ooops
You need to make array point to some memory you can write to. For example
DynamicArray *array = malloc(sizeof(DynamicArray));
First use this :
DynamicArray *array;
array = (DynamicArray *)malloc(sizeof(struct DynamicArray));
array->array = ...
If you don't initialize a point you can't dereference it because its point to NULL.
If I have several linked structures in C like:
struct structA {
int a;
int b;
struct structA *next;
}
struct structB {
char a;
int b;
struct structB *next;
}
and I dynamically allocate memory like this:
struct structA *mystructA = (struct structA*) malloc(sizeof(struct structA));
mystructA->next = (struct structA*) malloc(sizeof(struct structA));
struct structB *mystructB = (struct structB*) malloc(sizeof(struct structB));
mystructB->next = (struct structB*) malloc(sizeof(struct structB));
do I always have to free it for each struct type like this:
struct structA *p, *pNext;
for (p = mystructA; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
struct structB *p, *pNext;
for (p = mystructB; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
or is there any generic solution? I assume there is no other solution because the free() procedure must know how many bytes have to be freed. But maybe I'm wrong and someone can teach me better.
The standard way is to make the "list part" the first element of the structure, and let each derived struct share this same prefix. Since the first element is guaranteed to be placed at offset zero this wil work.
Example snippet:
#include <stdlib.h>
#include <string.h>
struct list {
struct list *next;
};
struct structA {
struct list list;
int a;
int b;
};
struct structB {
struct list list;
char a;
int b;
};
void *create_any(size_t size)
{
struct list *this;
this = malloc (size);
if (!this) return this;
memset(this, 0, size);
this->next = NULL;
return this;
}
void free_all_any(struct list **lp) {
struct list *tmp;
while ((tmp = *lp)) { *lp = tmp->next; free(tmp); }
}
#define CREATE_A() create_any(sizeof(struct structA))
#define CREATE_B() create_any(sizeof(struct structB))
#define FREE_A(pp) free_any((struct list **) pp)
#define FREE_B(pp) free_any((struct list **) pp)
int main(void)
{
struct structA *ap;
struct structB *bp;
ap = CREATE_A ();
bp = CREATE_B ();
// some code here ...
FREE_A( &ap);
FREE_B( &bp);
return 0;
}
This is more or less the method used in the linux kernel, but a lot more preprocessor magic is used there. (and there is no malloc there, obviously)
Since free() accepts pointers to void * and structA and structB both have the same size, you can pass both pointer types.
This is, however, not optimal in terms of elegance. You should think about the following questions:
Why do you have two different structs with the same members?
Why do you not have a generic list item type, such as the following:
struct list_node {
void *data;
struct list_node *next;
}
Actually, this is a very interesting question. The part is true that you have to free() each struct type individually, as they have been malloc()-ed individually, and each memory block has been allocated specifically for that type.Also, on some systems char and int have different storage sizes, but you can try a solution like Phillip provided. For more info, read about the doom memory engine. On a side note, please don't cast malloc() in C. The funny thing is that once the program is terminated, the operating system will reclaim the memory, so if you only deallocate the structures near the end of the program, when you don't need them anymore, it may not be necessary to free() them
I'm trying to figure out how to initialize an array of pointers to linked lists that has a dynamic size based on user input.
I've got a struct as follows:
struct HashTable {
int tableSize;
int (*getKey)(void *);
char * (*toString)(void *);
void (*freeHashObject)(void *);
Boolean (*compare)(void *, void *);
ListPtr table;
};
The table variable is supposed to contain a dynamic number of linked lists depending on user input. You can assume that n is a valid integer and that createHashObject works as it is supposed to.
HashTablePtr table;
HashObjectPtr job;
table = createHashTable(n, getKey, toString, freeHashObject, compare);
for (i=0; i<n; i++)
{
job = createHashObject(firstInput);
HashInsert(table, job);
}
I believe the problem lies in createHashTable which is as follows.
HashTablePtr createHashTable(int size, int (*getKey)(void *),
char * (*toString)(void *), void (*freeHashObject)(void *),
Boolean (*compare)(void *, void *))
{
HashTablePtr h = (HashTablePtr)malloc(sizeof(HashTable));
//dont worry that i dont do things with the function pointers
h -> table = (ListPtr)malloc(sizeof(List)*size);
int i;
for (i = 0; i < size; i++)
{
h -> table[i] = createList(getKey, toString, freeHashObject);
}
}
The above code doesn't seem to correctly initialize all the linked lists. Here is the code for the createList function and the List struct.
ListPtr createList(int(*getKey)(void *),
char * (*toString)(void *),
void (*freeHashObject)(void *))
{
ListPtr list;
list = (ListPtr) malloc(sizeof(List));
list->size = 0;
list->head = NULL;
list->tail = NULL;
list->getKey = getKey;
list->toString = toString;
list->freeObject = freeHashObject;
return list;
}
struct list {
int size;
NodePtr head;
NodePtr tail;
int (*getKey)(void *);
char * (*toString)(void *);
void (*freeObject)(void *);
};
I am willing to wager that the issue lies in how I am defining the dynamically sized array of pointers to the linked lists and then initializing it. Can anyone offer me some help with that?
Thank you.
In your HashTable structure change the table definition to declare it as pointer, as below
struct HashTable {
...
ListPtr *table;
};
Then you can allocate as many you want which you have done correctly.
I have a struct called warehouse and a generic linked list and each item points to a warehouse struct.
typedef struct linked{
char type;
void * item;
struct linked * next;
struct linked * prev;
}LinkedList;
typedef struct warehouse{
char * name;
float volume;
float (* getPrice) (void * S);
float (* getTotalDollarAmount)(void * S);
}house_t;
When I tried to get the getPrice function pointer point to a function float price (void *S)
void menu (LinkedList *house){
char *c;
float num;
c = (char*)malloc(sizeof(char)*10);
LinkedList *i;
i = (LinkedList*)malloc(sizeof(LinkedList);
house_t *sk;
sk = (house_t *) malloc(sizeof(house_t));
//i->item = (house_t *) malloc(sizeof(house_t));
scanf("%c", c);
((house_t*)i->item)->getPrice = price;
sk=findhouse(house, c);
num = ((house_t*)i->item)->getPrice(sk);
printf("%f",num);
}
I got bad access error. Since every time I got a bad access error it was because I didn't allocate memory for something. But do I need to allocate memory for function pointer? If so, how?
Here's some more code
float price (void *S)
{
return ((house_t*)S)->volume;
}
LinkedList *i;
i = NewLinkedList();
/* ... snip ... */
LinkedList *NewLinkedList()
{
return NULL;
}
According to your definition of NewLinkedList(), the variable i is now NULL. You try and dereference it with i->item = ... but you can't do this if i is NULL. I think what you really want to do is allocate space for your linked list in your NewLinkedList function:
LinkedList * NewLinkedList()
{
LinkedList *result = malloc(sizeof(LinkedList));
result->type = '\0'; // set to suitable initial value
result->item = NULL;
result->next = NULL;
result->prev = NULL;
return result;
}
I want to have a stack that takes strings. I want to be able to push and pop strings off, as well as clear the whole stack. I think C++ has some methods for this. What about C?
Quick-and-dirty untested example. Uses a singly-linked list structure; elements are pushed onto and popped from the head of the list.
#include <stdlib.h>
#include <string.h>
/**
* Type for individual stack entry
*/
struct stack_entry {
char *data;
struct stack_entry *next;
}
/**
* Type for stack instance
*/
struct stack_t
{
struct stack_entry *head;
size_t stackSize; // not strictly necessary, but
// useful for logging
}
/**
* Create a new stack instance
*/
struct stack_t *newStack(void)
{
struct stack_t *stack = malloc(sizeof *stack);
if (stack)
{
stack->head = NULL;
stack->stackSize = 0;
}
return stack;
}
/**
* Make a copy of the string to be stored (assumes
* strdup() or similar functionality is not
* available
*/
char *copyString(char *str)
{
char *tmp = malloc(strlen(str) + 1);
if (tmp)
strcpy(tmp, str);
return tmp;
}
/**
* Push a value onto the stack
*/
void push(struct stack_t *theStack, char *value)
{
struct stack_entry *entry = malloc(sizeof *entry);
if (entry)
{
entry->data = copyString(value);
entry->next = theStack->head;
theStack->head = entry;
theStack->stackSize++;
}
else
{
// handle error here
}
}
/**
* Get the value at the top of the stack
*/
char *top(struct stack_t *theStack)
{
if (theStack && theStack->head)
return theStack->head->data;
else
return NULL;
}
/**
* Pop the top element from the stack; this deletes both
* the stack entry and the string it points to
*/
void pop(struct stack_t *theStack)
{
if (theStack->head != NULL)
{
struct stack_entry *tmp = theStack->head;
theStack->head = theStack->head->next;
free(tmp->data);
free(tmp);
theStack->stackSize--;
}
}
/**
* Clear all elements from the stack
*/
void clear (struct stack_t *theStack)
{
while (theStack->head != NULL)
pop(theStack);
}
/**
* Destroy a stack instance
*/
void destroyStack(struct stack_t **theStack)
{
clear(*theStack);
free(*theStack);
*theStack = NULL;
}
Edit
It would help to have an example of how to use it:
int main(void)
{
struct stack_t *theStack = newStack();
char *data;
push(theStack, "foo");
push(theStack, "bar");
...
data = top(theStack);
pop(theStack);
...
clear(theStack);
destroyStack(&theStack);
...
}
You can declare stacks as auto variables, rather than using newStack() and destroyStack(), you just need to make sure they're initialzed properly, as in
int main(void)
{
struct stack_t myStack = {NULL, 0};
push (&myStack, "this is a test");
push (&myStack, "this is another test");
...
clear(&myStack);
}
I'm just in the habit of creating pseudo constructors/destructors for everything.
Try GNU Obstacks.
From Wikipedia:
In the C programming language, Obstack is a memory-management GNU extension to the C standard library. An "obstack" is a "stack" of "objects" (data items) which is dynamically managed.
Code example from Wikipedia:
char *x;
void *(*funcp)();
x = (char *) obstack_alloc(obptr, size); /* Use the macro. */
x = (char *) (obstack_alloc) (obptr, size); /* Call the function. */
funcp = obstack_alloc; /* Take the address of the function. */
IMO what makes Obstacks special: It does not need malloc() nor free(), but the memory still can be allocated «dynamically». It is like alloca() on steroids. It is also available on many platforms, since it is a part of the GNU C Library. Especially on embedded systems it might make more sense to use Obstacks instead of malloc().
See Wikipedia's article about stacks.