#define UNIT_ARRAY_SIZE 1024
struct UserInfo {
char *name;
char *id;
int purchase;
};
struct DB {
struct UserInfo *pArray;
int curArrSize;
int numItems;
};
DB_T CreateCustomerDB(void) {
DB_T d;
d = (DB_T) calloc(1, sizeof(struct DB));
if (d == NULL) {
fprintf(stderr, "Can't allocate a memory for DB_T\n");
return NULL;
}
d->curArrSize = UNIT_ARRAY_SIZE; // start with 1024 elements
d->pArray = (struct UserInfo *)calloc(d->curArrSize,
sizeof(struct UserInfo));
if (d->pArray == NULL) {
fprintf(stderr, "Can't allocate a memory for array of size %d\n",
d->curArrSize);
free(d);
return NULL;
}
return d;
}
void
DestroyCustomerDB(DB_T d)
{
if (d == NULL) return;
struct UserInfo *p;
struct UserInfo *nextp;
for (p = d->pArray; p != NULL; p = nextp) {
nextp = p + 1;
free(p->id);
free(p->name);
}
free(d->pArray);
free(d);
}
when i test the DestoryCustomerDB it makes segmentation fault,
I think it is because, Although I allocated the memory to d->pArray with calloc, size d->curArrsize,
for loop in DestoryCustomerDB iterates forever. why this happen?
and am i doing freeing correctly? Thank you,
for (p = d->pArray; p != NULL; p = nextp) { can fail as there is no certain p == NULL.
Iterate to curArrSize instead.
while (d->curArrSize > 0) {
struct UserInfo *p = d->pArray[--(d->curArrSize)];
free(p->id);
free(p->name);
}
Related
i had to write my own free & malloc function.
So far I have not had a problem with that, but now I am supposed to merge neighboring free memory blocks in the halde_free() function. I would be really grateful if you could help me there.
#include "halde.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
/// Magic value for occupied memory chunks.
#define MAGIC ((void*)0xbaadf00d)
/// Size of the heap (in bytes).
#define SIZE (1024*1024*1)
/// Memory-chunk structure.
struct mblock {
struct mblock *next;
size_t size;
char memory[];
};
/// Heap-memory area.
char memory[SIZE];
/// Pointer to the first element of the free-memory list.
static struct mblock *head;
/// Helper function to visualise the current state of the free-memory list.
void halde_print(void) {
struct mblock* lauf = head;
// Empty list
if ( head == NULL ) {
fprintf(stderr, "(empty)\n");
return;
}
// Print each element in the list
while ( lauf ) {
fprintf(stderr, "(addr: 0x%08zx, off: %7zu, ", (uintptr_t) lauf, (uintptr_t)lauf - (uintptr_t)memory);
fflush(stderr);
fprintf(stderr, "size: %7zu)", lauf->size);
fflush(stderr);
if ( lauf->next != NULL ) {
fprintf(stderr, " --> ");
fflush(stderr);
}
lauf = lauf->next;
}
fprintf(stderr, "\n");
fflush(stderr);
}
void *halde_malloc (size_t size) {
static int initialized = 0;
if(initialized == 0){
head = (struct mblock *) memory;
head->size = sizeof(memory) - sizeof (struct mblock);
head->next = NULL;
initialized = 1;
}
if(size == 0){
return NULL;
}
struct mblock *lauf = head;
struct mblock **prev_next = &head;
while (lauf != NULL && lauf->size < size){
prev_next = &(lauf->next);
lauf = *prev_next;
}
if(lauf == NULL){
errno = ENOMEM;
return NULL;
}
if((lauf->size -size) <= sizeof(struct mblock)){
*prev_next = lauf->next;
} else {
//mblock anlegen und init.
struct mblock* neu = (struct mblock*) (lauf->memory + size);
neu->size = lauf->size - sizeof(struct mblock) - size;
neu->next = lauf->next;
//mblock anpassen
lauf->size = size;
//verketten wiederherstellen
*prev_next = neu;
}
lauf->next = MAGIC;
return lauf->memory;
}
void halde_free (void *ptr) {
if(ptr == NULL){
return;
}
struct mblock *mbp = (struct mblock *) ptr - 1;
if(mbp->next != MAGIC){
abort();
} else {
mbp->next = head;
head = mbp;
}
}
The code works so far but i have really no idea how to merge blocks..
The memory management runs over a simply linked lists. The variable head points to the first free memory block.
My idea is to merge the blocks directly in the else part but i don't have a good idea to do that..
Im trying to create a simple hashmap in C. The vs doesnt know any errors at compilation time. But during execution, the pointer to the structure is becoming a bad pointer.
hashedKey CXX0030: Error: expression cannot be evaluated
Here is the code for that, can anyone tell me why the code is crashing.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
//#include"Header.h"
struct hashItem{
char* hashedKey;
char* hashedValue;
hashItem* next;
};
#define SIZE 20
unsigned long hashf(char *str)
{
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash%SIZE;
}
struct hashItem * createNewItem(char *key, char *value){
struct hashItem *newKeyValue = (struct hashItem *)calloc(1, sizeof(struct
hashItem));
newKeyValue->hashedKey = (char*)malloc(sizeof(char) * 100);
newKeyValue->hashedValue = (char*)malloc(sizeof(char) * 100);
strcpy(newKeyValue->hashedKey, key);
newKeyValue->hashedValue = value;
newKeyValue->next = NULL;
return newKeyValue;
}
void put(struct hashItem** hashTable, char *key, char *value)
{
if (value == NULL)
return;
struct hashItem *newKeyValue = createNewItem(key, value);
int index = hashf(key);
if (hashTable[index] == NULL){
hashTable[index] = newKeyValue;
}
else
{
int inserted = 0;
struct hashItem *p = hashTable[index];
struct hashItem *q = NULL;
while (p != NULL){
int e = strcmp(p->hashedKey, newKeyValue->hashedKey);
if (e == 0){
if (q != NULL)
q->next = newKeyValue;
p->hashedValue = newKeyValue->hashedValue;
inserted = 1;
break;
}
q = p;
p = p->next;
}
if (!inserted)
q->next = newKeyValue;
}
}
struct hashItem * get(struct hashItem** hashTable, char *key){
if (hashTable == NULL)
return NULL;
int index = hashf(key);
if (hashTable[index] != NULL)
{
if (!strcmp(hashTable[index]->hashedKey, key)){
return hashTable[index];
}
else{
struct hashItem *p = hashTable[index];
while (p != NULL){
if (p->hashedKey == key)
return p;
p = p->next;
}
return NULL;
}
}
else{
return NULL;
}
}
int main(){
hashItem** hashtable = (hashItem**)malloc(sizeof(hashItem*)*20);
for (int i = 0; i < 20; i++){
hashtable[i] = (hashItem*)malloc(sizeof(hashItem));
hashtable[i]->hashedKey = NULL;
hashtable[i]->hashedValue = NULL;
hashtable[i]->next = NULL;
}
put(hashtable, "select", "marks");
hashItem* temp = (hashItem*)get(hashtable,"select");
printf("%s", temp->hashedKey);
int k;
scanf("%d", &k);
return 0;
}
During the debugging it seems the code is crashing at the exact line of:
struct hashItem *p = hashTable[index];
Please tell me why the code is crashing.
Basically you are thinking wrong about initializing the hash buckets.
In the main() function basically you only need to allocate memory for the buckets of the hash table, so you only need this:
hashItem** hashtable = (hashItem**)calloc(20, sizeof(hashItem**));
Pay attention that I am using calloc instead of malloc to make sure that it is going to initialize to NULL these memory region. So, basically here we created 20 buckets to be managed by the hash table.
Again, you should not do that for (int i = 0; i < 20; i++), that is wrong. You will manage the buckets at insertion time, so, when you are inserting something that is not in the hash table, then you allocate memory to that entry.
You are using a mixture of C and C++ here, please make sure to state that when you submit your question.
I will paste here the changes I made, because you were using a lot of casting to get the right pointer type, but it is not necessary if you usce the right structure types.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct _hashItem{
char* hashedKey;
char* hashedValue;
struct _hashItem* next;
} hashItem;
#define SIZE 20
unsigned long hashf(char *str)
{
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return (hash % SIZE);
}
hashItem * createNewItem(char *key, char *value){
hashItem *newKeyValue = (hashItem *)calloc(1, sizeof(
hashItem));
newKeyValue->hashedKey = (char*)malloc(sizeof(char) * 100);
newKeyValue->hashedValue = (char*)malloc(sizeof(char) * 100);
strcpy(newKeyValue->hashedKey, key);
newKeyValue->hashedValue = value;
newKeyValue->next = NULL;
return newKeyValue;
}
void put(hashItem** hashTable, char *key, char *value)
{
if (value == NULL)
return;
hashItem *newKeyValue = createNewItem(key, value);
int index = hashf(key);
if (hashTable[index] == NULL){
hashTable[index] = newKeyValue;
}
else
{
int inserted = 0;
hashItem *p = hashTable[index];
hashItem *q = NULL;
while (p != NULL){
int e = strcmp(p->hashedKey, newKeyValue->hashedKey);
if (e == 0){
if (q != NULL)
q->next = newKeyValue;
p->hashedValue = newKeyValue->hashedValue;
inserted = 1;
break;
}
q = p;
p = p->next;
}
if (!inserted)
q->next = newKeyValue;
}
}
hashItem * get(hashItem** hashTable, char *kAey){
if (hashTable == NULL)
return NULL;
int index = hashf(key);
if (hashTable[index] != NULL)
{
if (!strcmp(hashTable[index]->hashedKey, key)){
return hashTable[index];
}
else{
hashItem *p = hashTable[index];
while (p != NULL){
if (p->hashedKey == key)
return p;
p = p->next;
}
return NULL;
}
}
else{
return NULL;
}
}
int main(){
hashItem** hashtable = (hashItem**)calloc(20, sizeof(hashItem**));
put(hashtable, "select", "marks");
hashItem* temp = get(hashtable,"select");
printf("%s", temp->hashedKey);
int k;
scanf("%d", &k);
return 0;
}
Getting some segfault on the following algorithm to add an element to the correct bucket in a hashtable.
My structures are basic:
struct kv {
char* key;
unsigned val;
struct kv* next;
};
struct hashtable {
struct kv** table;
unsigned size;
};
And my buggy function:
struct kv* ht_find_or_put(char* word, unsigned value,
struct hashtablet* hashtable,
unsigned (*hash)(char*))
{
unsigned index = hash(word) % hashtable->size;
struct kv* ke = malloc(sizeof (struct kv));
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
{
if (strcmp(ke->key, word) == 0)
return ke;
}
if (ke == NULL)
{
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
return ke;
}
I know I haven't added yet all the tests (if malloc failed and such) just trying to debug this particular problem...
I'm allocating my table as such:
struct hashtable* hashtable_malloc(unsigned size)
{
struct hashtable *new_ht = malloc(sizeof(struct hashtable));
new_ht->size = size;
new_ht->table = malloc(sizeof(struct kv) * size);
for(unsigned i = 0; i < size; i++)
new_ht->table[i] = NULL;
return new_ht;
}
Any sort of help will greatly be appreciated. I'm only starting to learn.
The first issue is a memory leak, e.g. - you allocate memory using malloc, but than loses the reference to it, as you override the pointer:
// allocate memory
struct kv* ke = malloc(sizeof (struct kv));
// lose the reference
// VVVVVVVVVVV
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
The second issue, which probably causes the segfault, is that you try to de-reference a null pointer:
if (ke == NULL)
{
// ke is NULL, you can't de-reference it
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
The solution will be, IMHO, to allocate and put the new element, only upon failure to find it:
struct kv* ht_find_or_put(char* word, unsigned value, struct hashtablet* hashtable, unsigned (*hash)(char*))
{
unsigned index = hash(word) % hashtable->size;
struct kv* ke;
// first we try to find the node
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
{
if (strcmp(ke->key, word) == 0)
return ke;
}
// didn't find it - lets create and put a new one.
if (ke == NULL)
{
ke = malloc(sizeof (struct kv));
// later add a check if the allocation succeded...
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
return ke;
}
Since I didn't want to introduce entirely new code, that would just confuse you, I made the minimal changes to the original code.
I am having some difficulty assigning a pointer inside a struct to null. Since pointers are pass by value, I can't find an easy way to do this. Maybe its been a long day and I can''t think straight. Anyways, here is my code:
void
init_wordrec (wordrec *rec)
{
if ((rec = (wordrec *) malloc(sizeof(wordrec))) == NULL) {
perror("Malloc failed");
exit(1);
}
rec->word = NULL;
rec->hits = 0;
rec->nxt_wd = NULL;
}
Here is the wordrec struct:
typedef struct wordrec
{
char *word;
int hits;
struct wordrec *nxt_wd;
} wordrec;
I want the actual word pointer to point to null, unfortunately my attempts have only caused gcc to complain loudly.
EDIT: Here is a method where I pass in word struct.
void
add_word (char *word, wordrec *head)
{
wordrec *iter = head;
wordrec *tmp;
if (iter->word == NULL) { //This should be NULL but is not
if ((iter->word = (char *) malloc((strlen(word) + 1) * sizeof(char))) == NULL) {
perror("Malloc failed");
exit(1);
}
strncpy(iter->word, word, strlen(word) + 1);
iter->hits++;
init_wordrec (iter->nxt_wd);
} else if (strcmp(iter->word, word) < 0) {
init_wordrec (tmp);
if ((tmp->word = (char *) malloc((strlen(word) + 1) * sizeof(char))) == NULL) {
perror("Malloc failed");
exit(1);
}
strncpy(tmp->word, word, strlen(word) + 1);
tmp->hits++;
tmp->nxt_wd = head;
head = tmp;
} else if (strcmp(iter->word, word) > 0) {
add_word (word, iter->nxt_wd);
} else {
iter->hits++;
}
}
Main:
int
main()
{
wordrec head;
char word1[] = "Hello";
init_wordrec (&head);
add_word(word1, &head);
return 0;
}
Did you mean something like this:
void init_wordrec(wordrec **rec)
{
if ((*rec = (wordrec *) malloc(sizeof(wordrec))) == NULL) {
perror("Malloc failed");
exit(1);
}
(*rec)->word = NULL;
(*rec)->hits = 0;
(*rec)->nxt_wd = NULL;
}
....
wordrec *wr;
init_wordrec(&wr);
Assignment goes the other way — you assign a value, such as NULL, to a variable, such as rec->word.
You could pass a double pointer to the function:
void
init_wordrec (wordrec **rec)
{
if ((*rec = (wordrec *) malloc(sizeof(wordrec))) == NULL) {
perror("Malloc failed");
exit(1);
}
(*rec)->word = NULL;
(*rec)->hits = 0;
(*rec)->nxt_wd = NULL;
}
/* ... */
wordrec *wr = 0;
init_wordrec(&wr);
but since you're allocating in the function (so you're just going to throw away the value passed in) making it return the new record usually simplifies the code:
wordrec*
init_wordrec(void)
{
wordrec *rec = malloc(sizeof(*rec));
if (rec == NULL) {
perror("Malloc failed");
exit(1);
}
rec->word = NULL;
rec->hits = 0;
rec->nxt_wd = NULL;
return rec;
}
/* ... */
wordrec *wr = init_wordrec();
You shouldn't cast the result of malloc; it will make the code compile even if you fail to include its prototype, but will fail badly at runtime.
A simpler option would be:
void init_wordrec (wordrec *rec)
{
rec->word = NULL;
rec->hits = 0;
rec->nxt_wd = NULL;
}
which allows your code in main to remain unchanged:
int main()
{
wordrec head;
char word1[] = "Hello";
init_wordrec (&head);
Another advantage of this is that users of wordrec have the option to use automatic allocation or dynamic allocation (whereas the other proposed answers force dynamic allocation to be used).
I have been working on a post fix calculator for standard input and after working on it I ended up getting a saying segmentation fault (core dumped) it doesn't say where it occurs or what caused it and after looking for an explanation of what it means I couldn't really find anything that would help me fix it. So I decided I might as well ask here this is all of the stuff I have so far.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct stack
{
int data;
struct stack *up;
};
void push( struct stack * ptr, int value)
{
struct stack * tmp;
tmp = malloc(sizeof(value));
tmp -> data = value;
tmp -> up = NULL;
}
int pop(struct stack * ptr)
{
int value;
struct stack * tmp;
tmp = ptr;
value = tmp-> data;
ptr = tmp -> up;
free(tmp);
return value;
}
int evaluate(int argc,const char * argv[],struct stack * ptr)
{
int h;
int i;
for (i = 0; i <= argc - 1; i++)
{
if (strcmp(argv[i], "M") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b*a;
push(ptr,h);
}
else if (strcmp(argv[i], "A") == 0)
{
printf("%s\n", "error \0");
int a = pop(ptr);
int b = pop(ptr);
h = b+a;
push(ptr,h);
}
else if (strcmp(argv[i], "D") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b/a;
push(ptr,h);
}
else if (strcmp(argv[i], "S") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b-a;
push(ptr,h);
}
else
{
printf("%s", "Not an operator");
}
}
return pop(ptr);
}
int main(int argc, const char *argv[])
{
struct stack s;
struct stack *ptr = s.up;
evaluate(argc,argv,ptr);
return EXIT_SUCCESS;
}
In main you create struct stack s; and don't initialize it.
Then you pass s.up as the third argument of evaluate.
And evaluate eventually calls pop on s.up, which calls free on s.up. But s.up is still uninitialized, so it crashes.
It's because you are allocating the structs wrong, here
tmp = malloc(sizeof(value));
you are allocating enough space for a int value, so the code that follows invokes undefined behavior leading in your case to a segmentation fault, try it this way
tmp = malloc(sizeof(struct stack));
or
tmp = malloc(sizeof(*tmp));
also, always check the success of malloc() before dereferencing the pointer, like this
void push(struct stack *ptr, int value)
{
struct stack *tmp;
tmp = malloc(sizeof(*tmp));
if (tmp == NULL)
return;
tmp->data = value;
tmp->up = NULL;
}