Invalid pointer address when trying to free - c

So all I'm trying to do is free a pointer and it just gives me the error 'invalid address'; though the address is clearly valid, as illustrated by the prints I put in. It tries to free the address of the pointer, but still fails. Through valgrind, it gives the error invalid free() saying the address is on thread 1's stack? The code below is runnable; can anyone help?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define SUCC 1
#define FAIL -1
typedef struct bucket {
char *key;
void *value;
struct bucket *next;
} Bucket;
typedef struct {
int key_count;
int table_size;
void (*free_value)(void *);
Bucket **buckets;
} Table;
extern unsigned int hash_code(const char *key) {
unsigned int hash = 0, i = 0;
while(i < strlen(key)) {
hash ^= ((hash << 3) | (hash >> 29)) + key[i++];
}
return hash;
}
/*Makes copy of string and returns pointer to it*/
char * cpy(const char *str) {
char *new = malloc(sizeof(char *));
if(new)
strcpy(new, str);
return new;
}
int create_table(Table ** table, int table_size, void (*free_value)(void *)) {
*table = malloc(sizeof(Table));
if(table && table_size != 0) {
int i = 0;
(*table)->key_count = 0;
(*table)->table_size = table_size;
(*table)->free_value = free_value;
(*table)->buckets = calloc(table_size, sizeof(Bucket *));
while(i < table_size)
(*table)->buckets[i++] = NULL;
return SUCC;
}
return FAIL;
}
int put(Table * table, const char *key, void *value) {
if(table && key) {
int hash = hash_code(key)%table->table_size;
Bucket *curr = table->buckets[hash];
while(curr) {
if(strcmp(curr->key, key) == 0) {
if(table->free_value)
table->free_value(curr->value);
printf("addr of ptr: %p\n", value);
curr->value = value;
printf("addr of curr ptr: %p\n", curr->value);
return SUCC;
}
curr = curr->next;
}
curr = malloc(sizeof(Bucket));
curr->key = cpy(key);
printf("addr of ptr: %p\n", value);
curr->value = value;
printf("addr of curr ptr: %p\n", curr->value);
curr->next = table->buckets[hash];
table->buckets[hash] = curr;
table->key_count++;
return SUCC;
}
return FAIL;
}
int remove_entry(Table * table, const char *key) {
if(table && key) {
int hash = hash_code(key)%(table->table_size);
Bucket *curr = table->buckets[hash], *prev = table->buckets[hash];
while(curr) {
printf("attempt");
if(strcmp(curr->key, key) == 0) {
void * test = curr->value;
printf("at addr %p\n", test);
table->free_value(test);
printf("freed");
if(table->free_value){
table->free_value(curr->value);
}
free(curr->key);
curr->key = NULL;
curr->value = NULL;
table->key_count--;
if(prev == curr)
table->buckets[hash] = curr->next;
else
prev->next = curr->next;
free(curr);
curr = NULL;
return SUCC;
}
prev = curr;
curr = curr->next;
}
}
return FAIL;
}
And the test file that shows the error:
#include <stdio.h>
#include <stdlib.h>
#include "htable.h"
int main() {
Table *t;
int num2 = 3;
printf("create: %d\n",create_table(&t, 2, free));
printf("addr of ptr: %p\n",(void *)&num2);
printf("put %s: %d\n","test",put(t, "test", &num2));
printf("rem key: %d\n",remove_entry(t, "test"));
return 0;
}

This is broken:
char *new = malloc(sizeof(char *));
The amount of memory you need is based on what you need to store, which is the string. You want:
char *new = malloc(strlen(str) + 1);
Or, better yet, just use strdup.

You are trying to free() a stack variable: num2 (in main()):
int num2 = 3;
Later, you have this call:
printf("put %s: %d\n","test",put(t, "test", &num2));
You're passing the address of num2 to put(), which means that remove_entry() will try to free it later. This is illegal. You cannot free a variable allocated on the stack. You should dynamically allocate num2 instead:
int* num2 = malloc(sizeof(int));
*num2 = 3;
There's another problem as well though. In this code:
void * test = curr->value;
printf("at addr %p\n", test);
table->free_value(test);
printf("freed");
if(table->free_value){
table->free_value(curr->value);
}
You are freeing curr->value twice, because you're freeing test which is just a copy of the pointer.

Related

Hashtable with linked list not work in c?

I've a problem with memory allocation for an hash table with linked list (for avoid collisions) in C.
I think that the problem is on allocation of an item.
I've made two scruct, one for the single item and one for the table.
The first have two pointer to next and prev item.
Please help me.
I stay on this code until 3 days.
The code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CAPACITY 50000
unsigned long hash(char *str) {
unsigned long int stringsum = 0;
for(; *str != '\0'; str++) {
stringsum += *str;
}
return stringsum % CAPACITY;
}
typedef struct item {
char *value;
char *key;
struct item *next;
struct item *prev;
} ht_item;
typedef struct hashtable {
ht_item **items;
int dim;
int count;
} HashTable;
HashTable* create_table(int size); HashTable* create_item(HashTable *table, char *value, char *key);
void print_table(HashTable* table, int dim);
int main(void) {
HashTable *table = create_table(CAPACITY);
table = create_item(table, "Giuseppe", "Nome");
print_table(table, CAPACITY);
return 0;
}
HashTable* create_item(HashTable *table, char *value, char *key) {
unsigned long index = hash(key);
printf("%u", index);
ht_item *_iterator; ht_item *prev;
for(_iterator = table->items[index], prev = NULL; _iterator != NULL; prev = _iterator, _iterator = _iterator->next);
_iterator = (ht_item*)malloc(sizeof(ht_item));
_iterator->key = (char*)malloc(200);
_iterator->value = (char*)malloc(200);
strcpy(_iterator->key, key);
strcpy(_iterator->value, value);
_iterator->next = NULL;
_iterator->prev = prev;
return table;
}
HashTable* create_table(int size)
{
HashTable *table = (HashTable*)malloc(sizeof(HashTable));
table->dim = size;
table->items = (ht_item**)calloc(size, sizeof(ht_item*));
for(int i = 0; i < size; i++){
table->items[i] = NULL;
}
return table;
}
void print_table(HashTable* table, int dim) {
for(int i = 0; i < CAPACITY; i++)
{
if(table->items[i] != NULL)
{ ht_item *_iterator = (ht_item*)malloc(sizeof(ht_item));
for(_iterator = table->items[i]; _iterator != NULL;
_iterator = _iterator->next)
{
printf("Key: %s\tValue: %s\n", _iterator->key, _iterator->value);
} free(_iterator);
}
}
}
Made some changes in your code. Please read through the blocks containing // CHANGE HERE comment.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CAPACITY 50000
// CHANGE HERE - additional parameter, value to be used for modulo
unsigned long hash(char *str, unsigned int mod_value) {
unsigned long int stringsum = 0;
for(; *str != '\0'; str++) {
stringsum += *str;
}
// CHANGE HERE - use mod_value instead of CAPACITY
return stringsum % mod_value;
}
typedef struct item {
char *value;
char *key;
struct item *next;
struct item *prev;
} ht_item;
typedef struct hashtable {
ht_item **items;
int dim;
int count;
} HashTable;
HashTable* create_table(int size); HashTable* create_item(HashTable *table, char *value, char *key);
void print_table(HashTable* table, int dim);
int main(void) {
HashTable *table = create_table(CAPACITY);
table = create_item(table, "Giuseppe", "Nome");
print_table(table);
return 0;
}
HashTable* create_item(HashTable *table, char *value, char *key) {
// CHANGE HERE - function arguments validation
if (table == NULL)
{
return table;
}
if (value == NULL || key == NULL)
{
printf("Key or value is null\n");
return table;
}
// CHANGE HERE - pass table->dim to hash
unsigned long index = hash(key, table->dim);
printf("Index: %lu\n", index);
// CHANGE HERE - simplified the code a bit
ht_item* new_node = malloc(sizeof(ht_item));
new_node->key = malloc(200 * sizeof(char));
strncpy(new_node->key, key, 200);
new_node->value = malloc(200 * sizeof(char));
strncpy(new_node->value, value, 200);
// CHANGE HERE - if first node in index
if (table->items[index] == NULL)
{
table->items[index] = new_node;
return table;
}
ht_item *cur, *prev = NULL;
for(cur = table->items[index]; cur != NULL; prev = cur, cur = cur->next);
prev->next = new_node; // CHANGE HERE - it seems this line was missing
new_node->prev = prev;
new_node->next = NULL;
return table;
}
HashTable* create_table(int size)
{
HashTable *table = (HashTable*)malloc(sizeof(HashTable));
table->dim = size;
table->items = (ht_item**)calloc(size, sizeof(ht_item*));
for(int i = 0; i < size; i++){
table->items[i] = NULL;
}
return table;
}
void print_table(HashTable* table) {
// CHANGE HERE - function arguments validation
if (table == NULL)
{
printf("Table is null\n");
return;
}
// CHANGE HERE - change CAPACITY to dim
for(int i = 0; i < table->dim; i++)
{
//printf("i = %d [%d]\n", i, table->items[i] == NULL);
if(table->items[i] != NULL)
{
// CHANGE HERE - removed unnecessary malloc
ht_item *_iterator = NULL;
for(_iterator = table->items[i]; _iterator != NULL; _iterator = _iterator->next)
{
printf("Key: %s\tValue: %s\n", _iterator->key, _iterator->value);
}
}
}
}
The create_item function can and should be simplified.
I have put some comments inline.
HashTable* create_item(HashTable *table, char *value, char *key) {
// use modulo operator here, not in the hash function
unsigned long index = hash(key) % table->dim;
// nicer way of allocating
ht_item *insert = malloc(sizeof *insert);
// use strdup to avoid wasted memory and buffer overflows
insert->key = strdup(key);
insert->value = strdup(value);
// head insert rather than tail
insert->next = table->items[index];
table->items[index] = insert;
return table;
}
I dropped the use of the prev member. If you need that somewhere it's an exercise for you to add it. I don't think it's necessary for a simple hash table.

Hash Table Not Working Because of Segmentation Fault

I just learned about hash tables today and I tried to make one in C. I get a segmentation fault at line 90. It seems to store the data and retrieve the data fine. It's just when I try to use strcpy to copy the value in the data to a string in the calling function that I get a segmentation fault. I'm not really sure why this is happening since the data is printing out fine.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define size 100
//creates the lsit where the hash table will be stored
float round(int conver){
conver = conver*10.0f;
conver = (conver > (floor(conver)+0.5f)) ? ceil(conver) : floor(conver);
conver = conver/10.0f;
//If you're using C99 or better, rather than ANSI C/C89/C90, the following will also work.
//conver = roundf(conver*10.0f)/10.0f;
return conver;
}
int hash(char input[]){
//decides where a string should be stored
float number = 0;
for(int i = 0; i < strlen(input); i++){
int toAdd = input[i];
printf("to add: %d", toAdd);
number = number + toAdd;
printf("number: %f", number);
}
printf("number again: %f", number);
number /= strlen(input);
number = round(number);
printf("number divided: %f \n", number);
return number;
}
struct Node{
//blueprint for linked list node
struct Node *Next;
char data[];
};
struct Node *hashTable[];
struct Node *createNode(char *data){
//utility function to create a node in the linked list
struct Node *newNode = malloc(sizeof(struct Node));
newNode->Next = NULL;
strcpy(newNode->data, data);
return newNode;
};
void createHashTable(){
//creates the hash table before anything can be inserted
for(int i = 0; i < size; i++){
hashTable[i] = NULL;
}
}
void addToHashTable(char *input){
//adds to the hash table
int hashed = hash(input);
if(hashTable[hashed] == NULL){
hashTable[hashed] = createNode(input);
}
else{
struct Node *newNode = createNode(input);
newNode->Next = hashTable[hashed];
hashTable[hashed] = newNode;
}
}
char *search(char input[], char *writeTo){
//searches the hash table for a value
int hashed = hash(input);
printf("\nhashed: %d", hashed);
printf("\ndata: %s", hashTable[hashed]->data);
if(hashTable[hashed] == NULL){
strcpy(writeTo, "not found");
return;
}
else if(hashTable[hashed]->Next == NULL){
printf("\nit is: %s", hashTable[hashed]->data);
strcpy(writeTo, hashTable[hashed]->data);
return;
}
else{
struct Node *newNode = hashTable[hashed];
while(newNode != NULL){
if(newNode->data == input){
strcpy(writeTo, hashTable[hashed]->data);
return;
}
newNode = newNode->Next;
}
}
}
int main()
{
//main function
createHashTable();
addToHashTable("124");
char *writeTo;
search("124", writeTo);
printf("%s", writeTo);
return 0;
}
There were some bugs in it.
This code should work. I tried to change your code as minimal as possible.
Dont forget that you have to free() pointerstructures.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#define size 100
int _round(float conver){
conver = (conver > (floorf(conver)+0.5f)) ? ceilf(conver) : floorf(conver);
return (int) conver;
}
int hash(char input[]){
float number = 0;
for(int i = 0; i < strlen(input); i++)
{
int toAdd = (int) input[i];
number = number + toAdd;
}
number /= strlen(input);
number = _round(number);
return number;
}
struct Node{
struct Node *Prev;
struct Node *Next;
char *data;
};
struct Node *hashTable[size];
struct Node *createNode(char data[]){
struct Node *newNode = malloc(sizeof(struct Node));
newNode->Prev = NULL;
newNode->Next = NULL;
newNode->data = malloc( sizeof(char) * (strlen(data)));
strcpy(newNode->data, &data[0]);
return newNode;
};
void createHashTable(){
for(int i = 0; i < size; i++){
hashTable[i] = NULL;
}
}
void addToHashTable(char input[]){
int hashed = hash(input);
if(hashTable[hashed] == NULL){
hashTable[hashed] = createNode(input);
}
else{
struct Node *newNode = createNode(input);
newNode->Next = hashTable[hashed];
hashTable[hashed]->Prev = newNode;
hashTable[hashed] = newNode;
}
}
char *search(char input[]){
int hashed = hash(input);
printf("hashed: %d\n", hashed );
if(hashTable[hashed] == NULL){
char *writeTo = malloc( sizeof( char ) * 9);
strcpy(writeTo, "not found");
return writeTo;
}
else if(hashTable[hashed]->Next == NULL){
char *writeTo = malloc( sizeof(char) * (strlen(input)));
strcpy(writeTo, hashTable[hashed]->data);
return writeTo;
}
else{
struct Node *newNode = hashTable[hashed];
char *data = malloc( sizeof( char) * (strlen(input)));
strcpy( data, &input[0] );
data[strlen(input)] = '\0';
while(newNode != NULL){
if(strcmp(newNode->data, data) == 0 ){
char *writeTo = malloc( sizeof(char) * (strlen(input)));
strcpy(writeTo, newNode->data);
return writeTo;
}
newNode = newNode->Next;
}
free( data );
}
char *writeTo = malloc( sizeof( char ) * 9);
strcpy(writeTo, "not found");
return writeTo;
}
void freeHashTable()
{
struct Node * node;
for( int i = 0; i < size; ++i )
{
node = hashTable[i];
if( node != NULL )
{
while( node->Next != NULL )
{
node = node->Next;
}
while( node->Prev != NULL )
{
node = node->Prev;
free( (void*) node->Next->data );
free( (void*) node->Next );
}
free( (void*) node->data );
free( (void*) node );
}
}
}
int main()
{
createHashTable();
addToHashTable("142");
addToHashTable("124");
char *writeTo;
writeTo= search("142");
printf("%s\n", writeTo );
free( (void*) writeTo);
writeTo = search( "124" );
printf("%s\n", writeTo);
free( (void*) writeTo);
freeHashTable();
return 0;
}
First of all, when I run your code I don't get a segfault. Did you remove the use case where the segfault occured? If not, it could be a difference in our environments.
More importantly, your code seems to be riddled in small problems. If you get to fixing those one by one, then the important logical errors will have nowhere to hide.
Here is a (n unordered and incomplete) list of such problems:
In your round function, you are using floor and ceil, but you never include the math library.
In your search function, you are not returning a char*, you are returning nothing. The function header should reflect that.
In your search function, in the final else statement, in the while loop, the condition of the if statement compares two char* values, whereas I assume you mean to compare two strings.
In some of your print statements, you are not printing a new line or any other whitespace, making the results hard to read.

Allocate a big-chunk of memory and manage it afterwards

So, I'm currently going thorugh the book "Crafting Interpreters", one of the challenges is to allocate a big chunk of memory (only once) in the beginning of the program and manage it.
So far i've written this piece of code, but I'm not quite shure that I'm in the right direction.
#include <stdio.h>
#include "stdbool.h"
#include "stdlib.h"
typedef struct node {
_Bool free;
struct node* next;
} freeList;
#define IS_VALID(head) ((head)->next == NULL) ? 0 : 1
#define BLOCK_SIZE 8
void initFreeList(freeList* head, size_t size);
void* malloc_(freeList* head, size_t size);
void free_(freeList* head, void* var);
void initFreeList(freeList* head, size_t size)
{
freeList* ptr = NULL;
head->next = NULL;
head->free = true;
ptr = head;
for (int i = 0; i < size; i++) {
freeList* temp = malloc(sizeof(freeList*));
temp->next = NULL;
temp->free = true;
ptr->next = temp;
ptr = temp;
}
}
// Removes a node from the freeList and returns a void pointer.
void* malloc_(freeList* head, size_t size)
{
void* block = NULL;
freeList* ptr = NULL, *prev = NULL, *temp_ptr = NULL;
int counter = 0;
if (!IS_VALID(head))
return NULL;
while((size) % BLOCK_SIZE != 0)
size++;
for (ptr = head; ptr->next != NULL && ptr->free == true && counter < size;) {
counter += BLOCK_SIZE;
prev = ptr;
ptr = ptr->next;
ptr->free = false;
}
temp_ptr = ptr;
for (counter = 0; counter < size; counter += BLOCK_SIZE, temp_ptr = temp_ptr->next)
temp_ptr->free = false;
prev->next = temp_ptr->next;
temp_ptr->next = NULL;
block = ptr;
return block;
}
void free_(freeList* head, void* var)
{
_Bool flag = true;
while(head && flag) {
if (head->next == NULL) {
head->next = (freeList *) var;
head->next->free = true;
head->next->next = NULL;
flag = false;
}
head = head->next;
}
}
int main()
{
freeList* head = malloc(sizeof(freeList));
initFreeList(head, 10);
char* str = malloc_(head, 16);
int *var1 = malloc_(head, 8), *var2 = malloc_(head, 8);
sprintf(str, "%s", "Hello world !");
*var1 = 2000000000;
*var2 = 257;
free_(head, var1);
free_(head, str);
free_(head, var2);
printf("%s\n%d %d\n", str, *var1, *var2);
return 0;
}
I'm able to allocate memory for the variables in main, and when freeing the chunks are added back to the free list but some of them get lost, I guess it's because when I assigned memory using the
malloc_ im overwriting memory. What will be the right approach for this kind of problem ?

hashedmap and pointer to structs: CXX0030: Error: expression cannot be evaluated

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;
}

Segmentation fault for a weird unknown reason

I get a segmentation fault (core dumped) in the following peace of code (I'm implementing malloc(), free() and realloc()):
void free(void* ptr)
{
void* curr = head;
void* before = NULL;
int isLegal = 0;
/*Line X*/printf("curr is %p and ptr is %p\n", curr, ptr);
if(curr == ptr)
{
printf("aaa");
}
else
{
printf("bbb");
}
/*Some more code that actually frees the pointer and not relevant here*/
}
Now, you'd assume that it'd print aaa or bbb, it just announces a segmentation fault right after performing the printf() in line X. If I type "printf("a")" instead of the current printf() it won't print 'a' at all. That is really weird.
It prints:
curr is 0x86be000 and ptr is 0x86be000
and yet it would just exit and throw a segmentation fault right after.
The variable head is a static variable in that file. I really want to know where the problem is, it's really weird. Here's the statement from the header file:
void free(void* ptr);
As simple as that, do you see any problem in here?
The full code is available here but I doubt it's related, the program should, at least, print either 'aaa' or 'bbb', and it doesn't do that.
Any idea? I'm really desperate.
Following code complied with warnings but did execute perfectly
#include <unistd.h>
typedef struct metadata_block* p_block;
typedef struct metadata_block
{
size_t size;
p_block next;
int free;
}metadata_block;
void* malloc(size_t size);
void free(void* ptr);
void* realloc(void* ptr, size_t size);
//THE MAIN CODE IS AT THE BOTTOM//
#include <stdio.h>
static p_block head = NULL;
void* malloc(size_t size)
{
void* ptr;
int isOk = 1;
int temp = 0;
p_block curr = head;
if(size <= 0)
{
return NULL;
}
if(curr)
{
while(curr->next && isOk)
{
if(curr->free && size <= curr->size)
{
isOk = 0;
}
if(isOk)
{
curr = curr->next;
}
}
if(isOk) //what will happen if there isn't one free and big enough
{
ptr = sbrk(size + sizeof(metadata_block));
if((int)ptr <= 0)
return NULL;
((p_block)(ptr))->size = size;
((p_block)(ptr))->next = NULL; //next run it's the real next.
((p_block)(ptr))->free = 0;
return (ptr + sizeof(metadata_block));
}
else
{
if(curr->next)
{
ptr = curr;
if(curr->size == size || size > (curr->size - sizeof(metadata_block) - 1)) //not enough room for another block of memory
{
((p_block)(ptr))->free = 0;
return (ptr + sizeof(metadata_block));
}
temp = curr->size;
((p_block)(ptr))->size = size;
((p_block)(ptr))->free = 0;
((p_block)(ptr + sizeof(metadata_block) + size))->next = curr->next;
((p_block)(ptr))->next = ptr + sizeof(metadata_block) + size;
((p_block)(ptr + sizeof(metadata_block) + size))->size = temp - size;
((p_block)(ptr + sizeof(metadata_block) + size))->free = 1;
return (ptr + sizeof(metadata_block));
}
else
{
ptr = curr;
if((int)sbrk(size - curr->size) > 0)
{
((p_block)(ptr))->size = size;
((p_block)(ptr))->next = NULL; //next run it's the real next.
((p_block)(ptr))->free = 0;
return (ptr + sizeof(metadata_block));
}
return NULL;
}
}
}
else
{
ptr = sbrk(size + sizeof(metadata_block));
if((int)ptr <= 0)
return NULL;
head = ptr;
((p_block)(ptr))->size = size;
((p_block)(ptr))->next = NULL;
((p_block)(ptr))->free = 0;
}
return ptr;
}
void free(void* ptr)
{
void* curr = head;
void* before = NULL;
int isLegal = 0;
printf("curr is %p and ptr is %p\n", curr, ptr);
if(curr == ptr)
{
printf("aaa\n");
}
else
{
printf("bbb\n");
}
if(curr && ptr)
{
while(curr && !isLegal)
{
if(((p_block)(ptr)) == ((p_block)(curr))->next)
{
before = curr;
isLegal = 1;
curr = ((p_block)(curr))->next;
}
else
{
curr = ((p_block)(curr))->next;
}
}
if(isLegal)
{
curr = curr - sizeof(metadata_block);
if(((p_block)(curr))->next)
{
((p_block)(curr))->free = 1;
}
else
{
sbrk(0-(((p_block)(curr))->size + sizeof(metadata_block)));
((p_block)(before))->next = NULL;
}
}
}
}
void* realloc(void* ptr, size_t size)
{
void* ptr2 = malloc(size);
int i;
for(i = 0 ; i < size ; i++)
{
*((char*)(ptr2 + i)) = *((char*)(ptr + i));
}
free(ptr);
return ptr2;
}
int main()
{
printf("I'm in.\n");
char * str = malloc(10);
printf("After Malloc()\n");
void * ptr = (void *) str;
void * ptr2;
if(!str)
{
printf("Fail.\n");
}
strcpy(str,"TEST!\0");
printf("About to free\n");
free(str);
printf("free: OK!\n");
}
Output :
I'm in.
After Malloc()
About to free
curr is 0x1049000 and ptr is 0x1049000
aaafree: OK!
note - Instaed of your mm.h include I included codes in same file

Resources