Getting a segmentation fault error on an Open Addressing Hash Map? - c

I'm getting a segmentation fault error somewhere in my insert function. It says that its due to one of the 'strcmp' comparisons but i cant find the issue after looking at all of them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define INITIAL_CAPACITY 8
typedef struct node
{
unsigned int val;
char *key;
bool del;
} Node;
typedef Node * NodePtr;
typedef struct hashMap
{
NodePtr array;
size_t capacity;
size_t size;
} HashMap;
typedef HashMap * HMPtr;
//|-------------------------
HMPtr create();
void insert(HMPtr map, char *str);
//y
void resize_insert(HMPtr map, char *str);
//y
void print(HMPtr map);
void destroy(HMPtr *mapPtr);
void resize(HMPtr map);
//y
unsigned int hash(char *str);
//y
unsigned int pop(HMPtr map, char *key);
//y
//|-------------------------
int main(void)
{
HMPtr map = create();
insert(map, "Keathan");
insert(map, "Trey");
insert(map, "Noah");
insert(map, "Kleiner");
insert(map, "data");
insert(map, "Matthew");
print(map);
destroy(&map);
return 0;
}
unsigned int pop(HMPtr map, char *str)
{
unsigned int val = hash(str);
size_t h = (size_t)val;
size_t index = h % map->capacity;
for(size_t i = 0; map->array[index].key && strcmp(str, map->array[index].key);index = (h + ((++i) + i*i)/2)%map->capacity);
if (map->array[index].key)
{
map->array[index].del = true;
return map->array[index].val;
}
return 0;
}
unsigned int hash(char *str)
{
unsigned int out = 0;
unsigned int base = 31;
unsigned int factor = 1;
for (size_t i = 0; str[i] != 0; ++i)
{
out += (unsigned int)str[i] * factor;
factor *= base;
}
return out;
}
void resize(HMPtr map)
{
NodePtr old = map->array;
size_t old_capacity = map->capacity;
map->capacity = old_capacity * 2;
map->array = calloc(map->capacity, sizeof(Node));
for(size_t i = 0; i < old_capacity; ++i)
{
if(old[i].key)
{
if(old[i].del)
free(old[i].key);
else
resize_insert(map, old[i].key);
}
}
free(old);
}
void resize_insert(HMPtr map, char *str)
{
unsigned int val = hash(str);
size_t h = (size_t)val;
size_t index = h % map->capacity;
for (size_t i = 0; map->array[index].key; index = (h + ((++i) + i*i)/2)%map->capacity);
map->array[index].key = str;
map->array[index].val = val;
++(map->size);
}
void insert(HMPtr map, char *str)
{
unsigned int val = hash(str);
size_t h = (size_t)val;
size_t index = h % map->capacity;
size_t i;
NodePtr deleted = NULL;
for(i = 0; map->array[index].key && strcmp(str, map->array[index].key);index = (h + ((++i) + i*i)/2)%map->capacity)
if(!deleted && map->array[index].del)
{
deleted = map->array + index;
for(index = (h + ((++i) + i*i)/2)%map->capacity; map->array[index].key && strcmp(str, map->array[index].key); index = (h + ((++i) + i*i)/2)%map->capacity);
break;
}
if (map->array[index].key == NULL)
{
if(deleted)
{
free(deleted->key);
deleted->del = false;
index = deleted - map->array;
}
else if (++(map->size) >= 0.7*map->capacity)
{
resize(map);
index = h % map->capacity;
for (i = 0; map->array[index].key; index = (h + ((++i) + i*i)/2)%map->capacity);
}
map->array[index].key = calloc(strlen(str)+1, sizeof(char));
strcpy(map->array[index].key, str);
}
else
map->array[index].val = val;
}
HMPtr create()
{
HMPtr newList = malloc(sizeof(HashMap));
newList->size = 0;
newList->capacity = INITIAL_CAPACITY;
newList->array = calloc(newList->capacity, sizeof(NodePtr));
return newList;
}
void destroy(HMPtr *mapPtr)
{
free((*mapPtr)->array);
free(*mapPtr);
*mapPtr = NULL;
}
void print(HMPtr map)
{
for (size_t i = 0; i < map->capacity; ++i)
printf("%s;%u\n", map->array[i].key, map->array[i].val);
}
This is the Error i recieved after running on gdb
'''
Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse2_unaligned ()
at ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:30
30 ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: No such file or
directory.
'''
If anyone could spot the issue then that would help a lot. Thanks!

sizeof(nodePtr) is size of pointer you need sizeof(struct Node)
HMPtr create()
{
HMPtr newList = malloc(sizeof(HashMap));
newList->size = 0;
newList->capacity = INITIAL_CAPACITY;
newList->array = calloc(newList->capacity, sizeof(*newList->array));
return newList;
}

Related

C compressor - array subscript has type char

I am a real beginner to C so I have no idea why there is this error. I send the code to my friend and it worked for him without any errors and without altering it. I am running it on Oracle VM VirtualBox. There are more files to the compression program. While I want to use the cmake to create a Makefile and a running program this happens.
The error is in the function buildDictionary in condition if(isLeaf(root)).
How should I fix this problem? Any ideas?
#include "huffman.h"
void buildDictionary(struct MinHeapNode *root, int arr[], int top, HuffmanDictionary *dictionary) {
if (root->left) {
arr[top] = 0;
buildDictionary(root->left, arr, top + 1, dictionary);
}
if (root->right) {
arr[top] = 1;
buildDictionary(root->right, arr, top + 1, dictionary);
}
if (isLeaf(root)) {
dictionary->symbol[root->data] = root->data;
dictionary->code[root->data].code = encodeBits(arr, top);
dictionary->code[root->data].size = top;
}
}
void printDictionary(HuffmanDictionary *dictionary) {
for (int i = 0; i < 256; i++) {
int bs[MAX_TREE_HT];
decodeBits(dictionary->code[i].code, dictionary->code[i].size, bs);
printf("%c:", dictionary->symbol[i]);
for (int a = 0; a < dictionary->code[i].size; a++) {
printf("%d", bs[a]);
}
printf("\n");
}
}
long huffman_compress(const uint8_t *src, long size, uint8_t *dst, HuffmanDictionary *dictionary) {
FreqencyData *fd = malloc(sizeof(FreqencyData) * 256);
buildFrequencyData(src, size, fd);
uint8_t words[256];
int frequencies[256];
int count = 0;
for (int a = 0; a < 256; a++) {
if (fd[a].frequency > 0) {
words[count] = (uint8_t) a;
frequencies[count] = fd[a].frequency;
count++;
}
}
struct MinHeapNode *root
= buildHuffmanTree(words, frequencies, count);
int arr[MAX_TREE_HT], top = 0;
buildDictionary(root, arr, top, dictionary);
uint8_t *bits = malloc(size * MAX_TREE_HT);
memset(bits, 0, size * MAX_TREE_HT);
long numOfBits = 0;
for (long i = 0; i < size; i++) {
int n = dictionary->code[src[i]].size;
uint32_t b = dictionary->code[src[i]].code;
int bs[n];
decodeBits(b, n, bs);
for (int a = 0; a < n; a++) {
bits[numOfBits + a] = bs[a];
}
numOfBits += n;
}
long cx = 0;
for (long i = 0; i < numOfBits; i += 8) {
int bs[8];
for (int a = 0; a < 8; a++) {
bs[a] = bits[i + a];
}
dst[cx] = encodeBitsArr(bs);
cx++;
}
return cx;
}
uint32_t encodeBits(int arr[], int n) {
uint32_t ret = 0;
for (int i = 0; i < n; i++) {
if (arr[i] == 1) {
ret += pow(2, i);
}
}
return ret;
}
uint8_t encodeBitsArr(const int arr[8]) {
uint8_t ret = 0;
for (int i = 0; i < 8; i++) {
if (arr[i] == 1) {
ret += pow(2, i);
}
}
return ret;
}
void decodeBits(uint32_t b, int n, int bits[]) {
for (int i = 0; i < n; i++) {
bits[i] = (int) ((b >> i) & ONE_BIT_MASK_32BITS) != 0;
}
}
void decodeBitsFromByte(uint8_t b, int bits[]) {
for (int i = 0; i < 8; i++) {
bits[i] = (int) ((b >> i) & 0x01) != 0;
}
}
int findMatchingSymbol(const int bits[MAX_TREE_HT], HuffmanDictionary *dictionary,int* foundSize) {
for (int i = 0; i < 256; i++) {
int bs[MAX_TREE_HT];
decodeBits(dictionary->code[i].code, dictionary->code[i].size, bs);
bool found = false;
for (int a = 0; a < dictionary->code[i].size; a++) {
if (bs[a] == bits[a]) {
found = true;
} else {
found = false;
break;
}
}
if (found) {
*foundSize = dictionary->code[i].size - 1;
return dictionary->symbol[i];
}
}
return -1;
}
long huffman_extract(const uint8_t *src, long size, uint8_t *dst, HuffmanDictionary *dictionary) {
uint8_t *bits = malloc(size * 8);
memset(bits, 0, size * 8);
for (long i = 0; i < size; i++) {
int bs[8];
decodeBitsFromByte(src[i], bs);
for (int a = 0; a < 8; a++) {
bits[(i * 8) + a] = bs[a];
}
}
long foundBytes = 0;
int bs[MAX_TREE_HT];
for (long l = 0; l < size * 8; l++) {
for (int a = 0; a < MAX_TREE_HT; a++) {
bs[a] = bits[l + a];
}
int* foundSize = malloc(sizeof(int));
uint8_t b = findMatchingSymbol(bs, dictionary, foundSize);
if (b >= 0) {
dst[foundBytes] = b;
l+= *foundSize;
foundBytes++;
}
}
return foundBytes;
}
void buildFrequencyData(const uint8_t *src, long size, FreqencyData *fd) {
for (long i = 0; i < size; i++) {
fd[src[i]].frequency++;
}
}
struct MinHeapNode *newNode(uint8_t data, unsigned freq) {
struct MinHeapNode *temp = (struct MinHeapNode *)malloc(
sizeof(struct MinHeapNode));
temp->left = temp->right = NULL;
temp->data = data;
temp->freq = freq;
return temp;
}
struct MinHeap *createMinHeap(unsigned capacity) {
struct MinHeap *minHeap
= (struct MinHeap *) malloc(sizeof(struct MinHeap));
minHeap->size = 0;
minHeap->capacity = capacity;
minHeap->array = (struct MinHeapNode **)malloc(
minHeap->capacity * sizeof(struct MinHeapNode *));
return minHeap;
}
void swapMinHeapNode(struct MinHeapNode **a,
struct MinHeapNode **b) {
struct MinHeapNode *t = *a;
*a = *b;
*b = t;
}
void minHeapify(struct MinHeap *minHeap, int idx) {
int smallest = idx;
int left = 2 * idx + 1;
int right = 2 * idx + 2;
if (left < minHeap->size
&& minHeap->array[left]->freq
< minHeap->array[smallest]->freq)
smallest = left;
if (right < minHeap->size
&& minHeap->array[right]->freq
< minHeap->array[smallest]->freq)
smallest = right;
if (smallest != idx) {
swapMinHeapNode(&minHeap->array[smallest],
&minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
int isSizeOne(struct MinHeap *minHeap) {
return (minHeap->size == 1);
}
struct MinHeapNode *extractMin(struct MinHeap *minHeap) {
struct MinHeapNode *temp = minHeap->array[0];
minHeap->array[0] = minHeap->array[minHeap->size - 1];
--minHeap->size;
minHeapify(minHeap, 0);
return temp;
}
void insertMinHeap(struct MinHeap *minHeap,
struct MinHeapNode *minHeapNode) {
++minHeap->size;
int i = minHeap->size - 1;
while (i
&& minHeapNode->freq
< minHeap->array[(i - 1) / 2]->freq) {
minHeap->array[i] = minHeap->array[(i - 1) / 2];
i = (i - 1) / 2;
}
minHeap->array[i] = minHeapNode;
}
void buildMinHeap(struct MinHeap *minHeap) {
int n = minHeap->size - 1;
int i;
for (i = (n - 1) / 2; i >= 0; --i)
minHeapify(minHeap, i);
}
int isLeaf(struct MinHeapNode *root) {
return !(root->left) && !(root->right);
}
struct MinHeap *createAndBuildMinHeap(uint8_t data[],
int freq[], int size) {
struct MinHeap *minHeap = createMinHeap(size);
for (int i = 0; i < size; ++i)
minHeap->array[i] = newNode(data[i], freq[i]);
minHeap->size = size;
buildMinHeap(minHeap);
return minHeap;
}
struct MinHeapNode *buildHuffmanTree(uint8_t data[],
int freq[], int size) {
struct MinHeapNode *left, *right, *top;
struct MinHeap *minHeap
= createAndBuildMinHeap(data, freq, size);
while (!isSizeOne(minHeap)) {
left = extractMin(minHeap);
right = extractMin(minHeap);
top = newNode('$', left->freq + right->freq);
top->left = left;
top->right = right;
insertMinHeap(minHeap, top);
}
return extractMin(minHeap);
}
I didn't try anything as the code is running normally on other computers, but no on mine.
In the header file huffman.h, the structure MinHeapNode has a member data with type char that can have negative values on some architectures where type char is signed by default. This would cause undefined behavior when indexing dictionary->symbol[root->data] or dictionary->code[root->data] as you would be dereferencing elements outside the array boundaries. Just change the type to unsigned char or uint8_t to avoid this issue and fix the warning, that -Werror turned into an error.

Dijkstra’s shortest path algorithm in C - changing paramateres problem

this program is made to calculate shortest path between two vertexs. FUnction add_edge is adding edges and also their distance in format add_edge(g, 1, 2, 7);where first parameter is linked list, second and third paramater are edges and last one is distance between them.
Problem is that my program was made to insert it in this format add_edge(g, 'a', 'b', 7);but sending it as integer and in function making it to number with this action int a = a - 'a';.
and after i transformed my code to sending numbers instead of characters it stopped to work. showing no error but returning tash numbers.
Here's old code(working):
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct {
int vertex;
int weight;
} edge_t;
typedef struct {
edge_t **edges;
int edges_len;
int edges_size;
int dist;
int prev;
int visited;
} vertex_t;
typedef struct {
vertex_t **vertices;
int vertices_len;
int vertices_size;
} graph_t;
typedef struct {
int *data;
int *prio;
int *index;
int len;
int size;
} heap_t;
void add_vertex (graph_t *g, int i) {
int j;
if (g->vertices_size < i + 1) {
int size = g->vertices_size * 2 > i ? g->vertices_size * 2 : i + 4;
g->vertices = realloc(g->vertices, size * sizeof (vertex_t *));
for (j = g->vertices_size; j < size; j++)
g->vertices[j] = NULL;
g->vertices_size = size;
}
if (!g->vertices[i]) {
g->vertices[i] = calloc(1, sizeof (vertex_t));
g->vertices_len++;
}
}
void add_edge (graph_t *g, int a, int b, int w) {
a = a - 'a';
b = b - 'a';
add_vertex(g, a);
add_vertex(g, b);
vertex_t *v = g->vertices[a];
if (v->edges_len >= v->edges_size) {
v->edges_size = v->edges_size ? v->edges_size * 2 : 4;
v->edges = realloc(v->edges, v->edges_size * sizeof (edge_t *));
}
edge_t *e = calloc(1, sizeof (edge_t));
e->vertex = b;
e->weight = w;
v->edges[v->edges_len++] = e;
}
heap_t *create_heap (int n) {
heap_t *h = calloc(1, sizeof (heap_t));
h->data = calloc(n + 1, sizeof (int));
h->prio = calloc(n + 1, sizeof (int));
h->index = calloc(n, sizeof (int));
return h;
}
void push_heap (heap_t *h, int v, int p) {
int i = h->index[v] == 0 ? ++h->len : h->index[v];
int j = i / 2;
while (i > 1) {
if (h->prio[j] < p)
break;
h->data[i] = h->data[j];
h->prio[i] = h->prio[j];
h->index[h->data[i]] = i;
i = j;
j = j / 2;
}
h->data[i] = v;
h->prio[i] = p;
h->index[v] = i;
}
int min (heap_t *h, int i, int j, int k) {
int m = i;
if (j <= h->len && h->prio[j] < h->prio[m])
m = j;
if (k <= h->len && h->prio[k] < h->prio[m])
m = k;
return m;
}
int pop_heap (heap_t *h) {
int v = h->data[1];
int i = 1;
while (1) {
int j = min(h, h->len, 2 * i, 2 * i + 1);
if (j == h->len)
break;
h->data[i] = h->data[j];
h->prio[i] = h->prio[j];
h->index[h->data[i]] = i;
i = j;
}
h->data[i] = h->data[h->len];
h->prio[i] = h->prio[h->len];
h->index[h->data[i]] = i;
h->len--;
return v;
}
void dijkstra (graph_t *g, int a, int b) {
int i, j;
a = a - 'a';
b = b - 'a';
for (i = 0; i < g->vertices_len; i++) {
vertex_t *v = g->vertices[i];
v->dist = INT_MAX;
v->prev = 0;
v->visited = 0;
}
vertex_t *v = g->vertices[a];
v->dist = 0;
heap_t *h = create_heap(g->vertices_len);
push_heap(h, a, v->dist);
while (h->len) {
i = pop_heap(h);
if (i == b)
break;
v = g->vertices[i];
v->visited = 1;
for (j = 0; j < v->edges_len; j++) {
edge_t *e = v->edges[j];
vertex_t *u = g->vertices[e->vertex];
if (!u->visited && v->dist + e->weight <= u->dist) {
u->prev = i;
u->dist = v->dist + e->weight;
push_heap(h, e->vertex, u->dist);
}
}
}
v = g->vertices[i];
printf("%d\n", v->dist);
}
int main () {
graph_t *g = calloc(1, sizeof (graph_t));
add_edge(g, 'a', 'b', 7);
add_edge(g, 'a', 'c' ,9);
dijkstra(g, 'a', 'c');
return 0;
}
and here is my new code(that i want to make work):
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct {
int vertex;
int weight;
} edge_t;
typedef struct {
edge_t **edges;
int edges_len;
int edges_size;
int dist;
int prev;
int visited;
} vertex_t;
typedef struct {
vertex_t **vertices;
int vertices_len;
int vertices_size;
} graph_t;
typedef struct {
int *data;
int *prio;
int *index;
int len;
int size;
} heap_t;
void add_vertex (graph_t *g, int i) {
int j;
if (g->vertices_size < i + 1) {
int size = g->vertices_size * 2 > i ? g->vertices_size * 2 : i + 4;
g->vertices = realloc(g->vertices, size * sizeof (vertex_t *));
for (j = g->vertices_size; j < size; j++)
g->vertices[j] = NULL;
g->vertices_size = size;
}
if (!g->vertices[i]) {
g->vertices[i] = calloc(1, sizeof (vertex_t));
g->vertices_len++;
}
}
void add_edge (graph_t *g, int a, int b, int w) {
add_vertex(g, a);
add_vertex(g, b);
vertex_t *v = g->vertices[a];
if (v->edges_len >= v->edges_size) {
v->edges_size = v->edges_size ? v->edges_size * 2 : 4;
v->edges = realloc(v->edges, v->edges_size * sizeof (edge_t *));
}
edge_t *e = calloc(1, sizeof (edge_t));
e->vertex = b;
e->weight = w;
v->edges[v->edges_len++] = e;
}
heap_t *create_heap (int n) {
heap_t *h = calloc(1, sizeof (heap_t));
h->data = calloc(n + 1, sizeof (int));
h->prio = calloc(n + 1, sizeof (int));
h->index = calloc(n, sizeof (int));
return h;
}
void push_heap (heap_t *h, int v, int p) {
int i = h->index[v] == 0 ? ++h->len : h->index[v];
int j = i / 2;
while (i > 1) {
if (h->prio[j] < p)
break;
h->data[i] = h->data[j];
h->prio[i] = h->prio[j];
h->index[h->data[i]] = i;
i = j;
j = j / 2;
}
h->data[i] = v;
h->prio[i] = p;
h->index[v] = i;
}
int min (heap_t *h, int i, int j, int k) {
int m = i;
if (j <= h->len && h->prio[j] < h->prio[m])
m = j;
if (k <= h->len && h->prio[k] < h->prio[m])
m = k;
return m;
}
int pop_heap (heap_t *h) {
int v = h->data[1];
int i = 1;
while (1) {
int j = min(h, h->len, 2 * i, 2 * i + 1);
if (j == h->len)
break;
h->data[i] = h->data[j];
h->prio[i] = h->prio[j];
h->index[h->data[i]] = i;
i = j;
}
h->data[i] = h->data[h->len];
h->prio[i] = h->prio[h->len];
h->index[h->data[i]] = i;
h->len--;
return v;
}
void dijkstra (graph_t *g, int a, int b) {
int i, j;
for (i = 0; i < g->vertices_len; i++) {
vertex_t *v = g->vertices[i];
v->dist = INT_MAX;
v->prev = 0;
v->visited = 0;
}
vertex_t *v = g->vertices[a];
v->dist = 0;
heap_t *h = create_heap(g->vertices_len);
push_heap(h, a, v->dist);
while (h->len) {
i = pop_heap(h);
if (i == b)
break;
v = g->vertices[i];
v->visited = 1;
for (j = 0; j < v->edges_len; j++) {
edge_t *e = v->edges[j];
vertex_t *u = g->vertices[e->vertex];
if (!u->visited && v->dist + e->weight <= u->dist) {
u->prev = i;
u->dist = v->dist + e->weight;
push_heap(h, e->vertex, u->dist);
}
}
}
v = g->vertices[i];
printf("%d\n", v->dist);
}
int main () {
graph_t *g = calloc(1, sizeof (graph_t));
add_edge(g, 1, 2, 7);
add_edge(g, 1, 3 9);
dijkstra(g, 1, 3);
return 0;
}
I would be happy for any suggestion how to make it work even the old one to transform to accept numbers as paramateres and not 'characters'. thanks guys
John Bollinger's comment is right; you are testing different indices. Inside your dijkstra, you are assuming that the graph is fully populated, when it is really very sparse. If I have it correctly, you can ignore the nil nodes:
## -1,3 +1,4 ##
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
## -116,11 +117,17 ##
int i, j;
for (i = 0; i < g->vertices_len; i++) {
vertex_t *v = g->vertices[i];
- v->dist = INT_MAX;
- v->prev = 0;
- v->visited = 0;
+ if (v) {
+ v->dist = INT_MAX;
+ v->prev = 0;
+ v->visited = 0;
+ }
}
vertex_t *v = g->vertices[a];
+ if (v == 0) {
+ printf("-1\n");
+ return;
+ }
v->dist = 0;
heap_t *h = create_heap(g->vertices_len);
push_heap(h, a, v->dist);
## -129,10 +136,12 ##
if (i == b)
break;
v = g->vertices[i];
+ assert(v);
v->visited = 1;
for (j = 0; j < v->edges_len; j++) {
edge_t *e = v->edges[j];
vertex_t *u = g->vertices[e->vertex];
+ assert(u);
if (!u->visited && v->dist + e->weight <= u->dist) {
u->prev = i;
u->dist = v->dist + e->weight;
## -140,8 +149,11 ##
}
}
}
- v = g->vertices[i];
- printf("%d\n", v->dist);
+ if (v = g->vertices[i]) {
+ printf("%d\n", v->dist);
+ } else {
+ printf("-2\n");
+ }
}
At the very least, it doesn't fault with your config.

Runtime error on Leetcode

When I submit my code to Leetcode, it reported runtime error as:
Line 43: member access within null pointer of type 'struct bucket_item'.
I tested that case in my local, it works fine. I thought it maybe causeed by the platform and compiler are different. I then tried to test it on Leetcode Playground. It also worked very well. The Leetcode problem is: https://leetcode.com/problems/substring-with-concatenation-of-all-words/description/
Very appreciated if anyone could let me know what's wrong with my code.
typedef struct bucket_item {
char *str;
int count;
int ori_count;
} bucket_item;
typedef struct bucket {
int hashIndex;
int itemsCount;
bucket_item *items;
} bucket;
bucket *hash_init(const int bucket_count)
{
bucket *buckets = malloc(sizeof(bucket) * bucket_count);
for (int i = 0; i < bucket_count; ++i)
{
buckets[i].items = NULL;
buckets[i].itemsCount = 0;
}
return buckets;
}
int get_hash(char *str, const int bucket_count) {
const int str_len = strlen(str);
int base = 0;
int i = 0;
while (str[i] != '\0')
{
base += str[i];
i++;
}
return ((base >> 3) * 2654435761) % bucket_count;
}
bucket_item *hash_lookup(bucket *buckets, char *str, const int bucket_count)
{
const int hash_index = get_hash(str, bucket_count);
bucket *bucket = buckets + hash_index;
for (int i = 0; i < bucket->itemsCount; ++i)
{
if (strcmp(str, bucket->items[i].str) == 0) return bucket->items + i;
}
return NULL;
}
void hash_add(bucket *buckets, char *str, const int bucket_count)
{
bucket_item *item = hash_lookup(buckets, str, bucket_count);
if (item)
{
item->count++;
item->ori_count = item->count;
}
else {
const int hash_index = get_hash(str, bucket_count);
bucket *bucket = buckets + hash_index;
bucket->itemsCount++;
bucket->items = (bucket_item *)realloc(bucket->items, sizeof(bucket_item) * bucket->itemsCount);
bucket->items[bucket->itemsCount - 1].str = str;
bucket->items[bucket->itemsCount - 1].count = 1;
bucket->items[bucket->itemsCount - 1].ori_count = 1;
}
}
void hash_free(bucket *buckets, const int bucket_count)
{
for (int i = 0; i < bucket_count; ++i)
{
free(buckets[i].items);
buckets[i].items = NULL;
}
free(buckets);
buckets = NULL;
}
bool is_match(char* str, bucket *hashmap, int bucket_count, char **words, int word_len, int word_size)
{
bool found = true;
char *subStr = malloc(sizeof(char) * (word_len + 1));
subStr[word_len] = '\0';
for (int i = 0; i < word_size; ++i)
{
memcpy(subStr, str + i * word_len, word_len);
bucket_item *item = hash_lookup(hashmap, subStr, bucket_count);
if (item)
{
item->count--;
}
else
{
found = false;
}
}
free(subStr);
subStr = NULL;
for (int i = 0; i < word_size; ++i)
{
bucket_item *item = hash_lookup(hashmap, words[i], bucket_count);
if (item->count != 0) {
found = false;
}
}
for (int i = 0; i < word_size; ++i)
{
bucket_item *item = hash_lookup(hashmap, words[i], bucket_count);
item->count = item->ori_count;
}
return found;
}
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
int* findSubstring(char* s, char** words, int wordsSize, int* returnSize) {
if (wordsSize == 0) return NULL;
const int word_len = strlen(words[0]);
// prepare hashmap
bucket *hashmap = hash_init(wordsSize);
for (int i = 0; i < wordsSize; ++i)
{
hash_add(hashmap, words[i], wordsSize);
}
// loop long string.
int *ret = malloc(sizeof(int) * 1000);
*returnSize = 0;
const int s_len = strlen(s);
const int sub_strlen = word_len * wordsSize;
for (int i = 0; i < s_len; ++i)
{
const bool found = is_match(s + i, hashmap, wordsSize, words, word_len, wordsSize);
if (found)
{
ret[*returnSize] = i;
(*returnSize)++;
}
}
hash_free(hashmap, wordsSize);
ret = (int*)realloc(ret, sizeof(int) * (*returnSize));
return ret;
}
The case that report error is below:
int main() {
char *str = "ababaab";
char **words[] = { "ab", "ba", "ba" };
int returnSize = 0;
int *result = findSubstring(str, words, 3, &returnSize);
return 0;
}
When you call the hash_lookup function, it could return NULL in some cases. So when you use item->count in the next line, you may access a NULL pointer.
You should ensure that item isn't NULL first, and than use item->count, like so:
for (int i = 0; i < word_size; ++i)
{
bucket_item *item = hash_lookup(hashmap, words[i], bucket_count);
if (item != NULL && item->count != 0) {
found = false;
}
}
for (int i = 0; i < word_size; ++i)
{
bucket_item *item = hash_lookup(hashmap, words[i], bucket_count);
if (item != NULL) {
item->count = item->ori_count;
}
}

C int pointer allocation size [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
its a very very anoing problem what i get. My problem is, gcc seems not allocate enough space to my int pointer.
Here is the code:
fns = (int*)calloc(c,sizeof(int));
So, after then i fill up this in a simple loop ones and zeros:
offset = seekToFirstParam(fnString,n);
i = 0;
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
fns[i] = 1;
} else {
fns[i] = 0;
}
i++;
}
So this is a "flag" array, but when i debug this, and print the elements i get:
156212102, 0, 0, 0, 1, 1
Or som. like this. I don't get it, because if in the calloc method i write 1000 like this:
fns = (int*)calloc(1000,sizeof(int));
After works fine.
Ok, this is a hole function:
char **readFnParams(char *fnString, int n, int *count, int **func) {
char **tmp;
int *fns = NULL;
int c,i = 0,offset,s;
c = getParamsCount(fnString,n);
if (!c) {
return NULL;
}
tmp = (char**)calloc(c,sizeof(char));
fns = (int*)calloc(c,sizeof(int*));
offset = seekToFirstParam(fnString,n);
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
tmp[i] = readNextFunctionParam(fnString,n,offset,&s);
offset = seekToNextParam(fnString,n,offset + s - 1);
fns[i] = 1;
} else {
fns[i] = 0;
offset = seekToNextParam(fnString,n,offset);
}
i++;
}
*func = fns;
*count = c;
return tmp;
}
:) Ok, this is a hole .c file. Yes my previous q. end this connected, becouse its a homework.
#ifndef exccel_builder_source
#define exccel_builder_source
#include "exccel_builder.h"
#include "exccel_utils.h"
#include "exccel_function.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
table* _processing;
//A végére fűzi az új elemeket
void addProcess(cell_process **LIST, cell_process *new) {
if (*LIST == NULL) {
new->next = NULL;
*LIST = new;
return;
}
new->next = *LIST;
*LIST = new;
}
void build(table* table) {
int col = table->matrix->col;
int row = table->matrix->row;
int i,j;
table_cell *cellTemp;
_processing = table;
for (i = 1; i<=row; i++) {
for (j = 1; j<=col; j++) {
cellTemp = getCell(table,i,j);
if (cellTemp != NULL) {
buildCell(cellTemp);
}
}
}
}
void buildCell(table_cell *cell) {
//Begins with '='
if (isFunction(cell)) {
buildCellWithFunction(cell);
}
}
void printProcesses(cell_process *LIST, int tab) {
cell_process *tmp = NULL;
int i = 0;
tmp = LIST;
while(tmp != NULL) {
i = 0;
while(i++<tab) printf(" ");
printf("%s, %d, paramPos: %i\n",tmp->func->name,tmp->func->paramsCount,tmp->paramPos);
if (tmp->childs != NULL) {
i = 0;
while(i++<tab + 3) printf(" ");
printf("Childs\n");
printProcesses(tmp->childs, tab + 3);
}
tmp = tmp->next;
}
}
void buildCellWithFunction(table_cell *cell) {
cell_process *HEAD = NULL;
buildCellProcessList(cell,&HEAD);
cell->cp = HEAD;
printf("%d,%d - cella:\n",cell->row,cell->col);
printProcesses(HEAD,0);
}
void buildCellProcessList(table_cell *cell, cell_process **HEAD) {
char *fnString;
int size;
fnString = getCellStringValue(cell, &size);
readFn(fnString,size,1,cell,HEAD,-1);
}
int readFn(char *fnString, int n, int offset, table_cell *cell, cell_process **LIST, int paramPos) {
char *fnName, *fnParam;
int fnNameLength;
int *fnSig;
int fnSigN;
int fnSigI;
int sig;
exccel_var *vtmp;
exccel_function *ftmp;
cell_process *ptmp;
char **parameters;
int *fnIndexes;
int paramsCount;
int paramI;
int i;
fnName = readFnName(fnString,n,offset,&fnNameLength);
ftmp = getExccelFunction(fnName);
if (ftmp == NULL) {
return 0;
}
ptmp = (cell_process*)malloc(sizeof(cell_process));
ptmp->cell = cell;
ptmp->func = ftmp;
ptmp->paramPos = paramPos;
ptmp->t = _processing;
ptmp->childs = NULL;
addProcess(LIST,ptmp);
parameters = readFnParams(fnString,n,&paramsCount,&fnIndexes);
allocParams(ptmp->func,paramsCount);
paramI = 0;
fnSig = ftmp->signature;
fnSigN = fnSig[0];
fnSigI = 1;
while(fnSigI <= fnSigN) {
sig = fnSig[fnSigI];
if (sig == FN_SIG_RANGE) {
fnParam = parameters[paramI];
vtmp = createExccelRangeVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
paramI++;
} else if (sig == FN_SIG_LITERAL) {
fnParam = parameters[paramI];
if (fnIndexes[paramI] == 1) {
readFn(fnParam,strlen(fnParam),0,cell,&((*LIST)->childs),paramI);
} else {
vtmp = createExccelVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
}
paramI++;
} else if (sig == FN_SIG_LIST) {
while(paramI<paramsCount) {
fnParam = parameters[paramI];
if (fnIndexes[paramI] == 1) {
readFn(fnParam,strlen(fnParam),0,cell,&((*LIST)->childs),paramI);
} else {
vtmp = createExccelVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
}
paramI++;
}
} else {
printf("Invalid signature %d\n",sig);
exit(1);
}
fnSigI++;
}
return 1;
}
char *readFnName(char *fnString, int n, int offset, int *size) {
char *fnName;
int nameBuffer, i, j;
i = offset;
j = 0;
nameBuffer = 8;
fnName = (char *)calloc(nameBuffer,sizeof(char));
while(*(fnString + i) != '(' && i<n) {
*(fnName + j++) = *(fnString + i++);
if (j>=nameBuffer) {
nameBuffer += 8;
fnName = (char *)realloc(fnName, nameBuffer);
}
}
*(fnName + j++) = '\0';
*size = j;
return fnName;
}
char **readFnParams(char *fnString, int n, int *count, int **func) {
char **tmp;
int *fns = NULL;
int c,i = 0,offset,s;
c = getParamsCount(fnString,n);
if (!c) {
return NULL;
}
tmp = (char**)calloc(c,sizeof(char));
fns = (int*)calloc(c,sizeof(*fns));
offset = seekToFirstParam(fnString,n);
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
tmp[i] = readNextFunctionParam(fnString,n,offset,&s);
offset = seekToNextParam(fnString,n,offset + s - 1);
fns[i] = 1;
} else {
fns[i] = 0;
offset = seekToNextParam(fnString,n,offset);
}
i++;
}
*func = fns;
*count = c;
return tmp;
}
int getParamsCount(char *fnString, int n) {
int i = 0, c = 0, jump = 0;
while(i<n) {
if (fnString[i] == '(') {
jump++;
} else if (fnString[i] == ',') {
if (jump == 1) c++;
} else if (fnString[i] == ')') {
jump--;
}
i++;
}
if (c > 0) {
return c + 1;
} else {
return 1;
}
}
int seekToFirstParam(char *fnString, int n) {
int i = 0;
while(fnString[i++] != '(' && i<n);
return i;
}
int seekToNextParam(char *fnString, int n, int offset) {
int i = offset;
while(fnString[i++] != ',' && i<n);
return i;
}
char *readNextParam(char *fnString, int n, int offset, int *size) {
char *params, c;
int paramBuffer, i, j;
i = offset;
j = 0;
paramBuffer = 8;
params = (char*)calloc(paramBuffer,sizeof(char));
while((c = fnString[i++]) != ',' && c != ')' && c != '(' && i<n) {
params[j++] = c;
if (j >= paramBuffer) {
paramBuffer += 8;
params = (char*)realloc(params,paramBuffer);
}
}
params[j] = '\0';
*size = j;
return params;
}
//Megfelelő számú nyitó ( - hez kell hogy legyen ugyanannyi )
char *readNextFunctionParam(char *fnString, int n, int offset, int *size) {
char *fn, c;
int fnBf, i, j, fnStarted = 0, fnClosed = 0;
i = offset;
j = 0;
fnBf = 8;
fn = (char*)calloc(fnBf, sizeof(char));
while((fnStarted != fnClosed || fnStarted == 0) && i<n) {
c = *(fnString + i++);
if (c == '(')
fnStarted++;
else if (c == ')')
fnClosed++;
*(fn + j++) = c;
if (j >= fnBf) {
fnBf += 8;
fn = (char*)realloc(fn, sizeof(char) * fnBf);
}
}
//*(fn + j++) = ')';
*(fn + j++) = '\0';
*size = j;
return fn;
}
#endif
And input like this:
=SZORZAT(MDETERM(A1:D4),NAGY(A1:D4,0),10,20,30)
It looks to me like you aren't allocating correctly, you have:
tmp = (char**)calloc(c,sizeof(char));
The first line, tmp, is allocating c elements of size char (c elements of 1 byte), I think you want c elements of size char * (c elements of size 4 or 8 bytes per element depending on if you are 32 or 64 bit platform). Since your routine readNextParam() is returning char * to store in this array, you need to change the calloc sizeof for tmp to:
tmp = calloc(c,sizeof(char*));
Because of this, I believe you have memory overwrites when you write into the tmp array that bleed into your other array. By making both "1000" elements, you've padded out that first calloc far enough that the overwrites are still in that same piece of memory.

Setting struct value = segfault

#include <stdio.h>
#include <stdlib.h>
#define true 1
struct hashRow {
char *key;
char *value;
};
struct hash_table {
int max;
int number_of_elements;
struct hashRow **elements;
};
int hashstring(const char *s)
{
int key = 0;
while (*s)
key = key * 37 + *s++;
return key;
}
int hash_fun(int key, int try, int max) {
return (key + try) % max;
}
struct hash_table *table;
int hash_insert(struct hashRow *data, struct hash_table *hash_table) {
int try, hash;
if(hash_table->number_of_elements < hash_table->max) {
return 0; // FULL
}
for(try = 0; true; try++) {
int hkey = hashstring(data->key);
hash = hash_fun(hkey, try, hash_table->max);
if(hash_table->elements[hash] == 0) { // empty cell
hash_table->elements[hash] = data;
hash_table->number_of_elements++;
return 1;
}
}
return 0;
}
struct hashRow *hash_retrieve(char *key, struct hash_table *hash_table) {
int try, hash;
for(try = 0; true; try++) {
int hkey = hashstring(key);
hash = hash_fun(hkey, try, hash_table->max);
if(hash_table->elements[hash] == 0) {
return 0; // Nothing found
}
if(hash_table->elements[hash]->key == key) {
return hash_table->elements[hash];
}
}
return 0;
}
int hash_delete(char *key, struct hash_table *hash_table) {
int try, hash;
for(try = 0; true; try++) {
int hkey = hashstring(key);
hash = hash_fun(hkey, try, hash_table->max);
if(hash_table->elements[hash] == 0) {
return 0; // Nothing found
}
if(hash_table->elements[hash]->key == key) {
hash_table->number_of_elements--;
hash_table->elements[hash] = 0;
return 1; // Success
}
}
return 0;
}
void insertsomething()
{
struct hashRow *toInsert;
toInsert = (struct hashRow *)malloc(sizeof(*toInsert));
printf("toInsert declared\n");
char *k = (char*)malloc(sizeof(char*));
char *v = (char*)malloc(sizeof(char*));
k = "sayhello";
v = "hello";
this is where I seem to be having the problem.
toInsert->key = k;
toInsert->value = v;
hash_insert(toInsert, table);
}
int main()
{
printf("calling insertsomething.\n");
insertsomething();
struct hashRow *gotten;
gotten = hash_retrieve("sayhello", table);
printf("test: %s\n", gotten->value);
}
I'm trying to create a hash table, but whenever I try to set a value in the toInsert struct pointer it segfaults. Can someone explain to me what I am doing wrong?
Try this:
void insertsomething()
{
struct hashRow *toInsert;
toInsert = (struct hashRow *)malloc(sizeof(*toInsert));
printf("toInsert declared\n");
/*
char *k = (char*)malloc(sizeof(char*)); // wrong size
char *v = (char*)malloc(sizeof(char*)); // wrong size
k = "sayhello"; // bad assignment
v = "hello"; // bad assignment
*/
toInsert->key = strdup("sayhello");
toInsert->value = strdup("hello");
hash_insert(toInsert, table);
}
Also, I can't spot where you reserve memory for your hash_table. Is it hidden somewhere else??

Resources