C array being overwritten/deleted? very confused - c

I am working on a project in C and it is working great except for one function which seems to be overwriting my array and writing weird numbers such as 1970802352 which keeps count of word occurrences in a file
this is my header file:
#ifndef LIST_H
#define LIST_H
struct Node_{
char* word;
//array holding names of files word occurs in
char **filesIn;
int numFilesIn;
//array holding count of how many times word occured in file
int* occursIn;
struct Node_ *next;
int isHead;
};
typedef struct Node_ Node;
int insert(char *wordToAdd, char *File);
int addOccur(Node *addedTo, char *File);
Node *createNode(char *wordToAdd, char *File);
void destroyNodes();
#endif
and this is the function that keeps overwriting the array:
Node *head;
int insert(char *wordToAdd, char *File){
if(head == NULL){
Node *new;
new = createNode(wordToAdd, File);
new->isHead = 1;
head = new;
return 0;
}
else{
Node *trace;
trace = head;
char *traceWord;
int wordSize;
wordSize = strlen(trace->word);
traceWord = (char*) malloc(wordSize + 1);
strcpy(traceWord, trace->word);
int a =strcmp(wordToAdd, traceWord);
free(traceWord);
if(a == 0){
int b = addOccur(trace, File);
//printf("addOccur returned %d\n", b);
return 0;
}
if(a < 0){
Node *Insert = createNode(wordToAdd, File);
trace->isHead = 0;
Insert->isHead = 1;
Insert->next = trace;
head = Insert;
return 0;
}
else{
Node *backTrace;
backTrace = head;
while(trace->next != NULL){
trace = trace->next;
traceWord = trace->word;
a = strcmp(wordToAdd, traceWord);
if(a < 0){
Node* Insert = createNode(wordToAdd, File);
Insert->next = trace;
backTrace->next = Insert;
return 0;
}
if(a == 0){
addOccur(trace, File);
//free(wordToAdd);
return 0;
}
if(a > 0){
backTrace = trace;
continue;
}
}
Node *Insert = createNode(wordToAdd, File);
trace->next = Insert;
return 0;
}
}
return 1;
}
and the other functions are:
Node* createNode(char *wordToAdd, char *File){
Node *new;
new = (Node*)malloc(sizeof(Node));
memset(new, 0, sizeof(Node));
new->word = wordToAdd;
char **newArray;
newArray = (char**)malloc(sizeof(char*));
newArray[0] = File;
new->filesIn = newArray;
int a[1];
a[0] = 1;
new->occursIn = a;
//new->occursIn[0] = 1;
new->numFilesIn = 1;
return new;
}
int addOccur(Node *addedTo, char *File){
char **fileList = addedTo->filesIn;
char *fileCheck;
int i = 0;
int fileNums = addedTo->numFilesIn;
for(i = 0; i < fileNums; i++){
fileCheck = fileList[i];
if(strcmp(fileCheck, File) == 0){
int *add1;
add1 = addedTo->occursIn;
int j = add1[i];
j++;
add1[i] = j;
return 0;
}
}
int numberOfFilesIn;
numberOfFilesIn = addedTo->numFilesIn;
char **newList = (char**)malloc(sizeof(char*) * numberOfFilesIn + sizeof(char*));
i = 0;
char *dest;
char *src;
for(i = 0; i < numberOfFilesIn; i++){
src = fileList[i];
int len;
len = strlen(src);
dest = (char*)malloc(sizeof(char) * (len + 1));
strcpy(dest, src);
newList[i] = dest;
}
int len2;
len2 = strlen(File);
newList[i] = File;
free(fileList);
int r = addedTo->numFilesIn;
r++;
addedTo->numFilesIn = r;
addedTo->filesIn = newList;
i = 0;
int *g;
g = addedTo->occursIn;
int count2;
count2 = addedTo->numFilesIn;
count2++;
int a[count2];
for(i = 0; i < count2 -1; i++){
a[i] = g[i];
}
a[count2 - 1] = 1;
return 0;
}
When going to gdb i notice that the value of
head->occursIn[0]
changes after the line
wordSize = strlen(trace->word);
and I have no clue why.

In your CreateNode() function, you are not allocating storage for the occursIn array. You are simply declaring a local array within the function and then assigning the occursIn pointer:
int a[1];
a[0] = 1;
new->occursIn = a;
The array a[1] goes away when the createNode function returns, so at that point your occursIn pointer is pointing to a value that is subject to being overwritten.
And even if the storage was allocated correctly in createNode, you've set a fixed size for the array but your whole strategy depends on that array having an element for each file; and in addOccurs you don't do anything to allocate a new larger array for a new file.
You may want to re-evaluate your strategy and switch to using lists instead of arrays.

Related

c deleting element in dynamic struct

i'm trying to delete a single element in the struct and override this position with the last one.
Here is my code of a function:
int deleteElement(struct record **rec, int *length, int elementToDelete){
struct record *temp = NULL;
allocateTempMemory(&temp, ((*length) - 1));
for (int i = 0; i < ((*length) - 1); i++){
if (elementToDelete != i){
temp[i] = (*rec)[i];
temp[i].ID = (*rec)[i].ID;
temp[i].Salary = (*rec)[i].Salary;
strcpy(temp[i].Name, (*rec)[i].Name);
} else {temp[i] = (*rec)[(*length) - 1];
temp[i].ID = (*rec)[(*length) - 1].ID;
temp[i].Salary = (*rec)[(*length) - 1].Salary;
strcpy(temp[i].Name, (*rec)[(*length) - 1].Name);
};
}
free(*rec);
*rec = temp;
for (int i = 0; i < ((*length) - 1); i++){
(*rec)[i] = temp[i];
(*rec)[i].ID = temp[i].ID;
(*rec)[i].Salary = temp[i].Salary;
strcpy((*rec)[i].Name, temp[i].Name);
}
(*length)--;
free(temp);
return 1;
}
code of the struct
struct record{
char Name[100];
double Salary;
int ID;
};
code of the function allocateTempMemory:
int allocateTempMemory(struct record **temp, int length){
*temp = (struct record **)malloc(sizeof(struct record) * length);
if (temp == NULL){
return 0;
}
return 1;
}
However, it does not work properly. My guess are memory allocation issues (sometimes it runs through and sometimes it crashes immediately). Do you have any idea what the problem may be? thanks
You assign temp to *rect, than you free temp. basically you freed *rec. When you access *rec later it will cause crash.
*rec = temp;
....
free(temp); // cause *rec freed. Should not be freed.

Read from file to linked list C

I'm new to the C language, and I'm trying to make a calendar using SDL2, but for some reason my code just skips storing the first data. When I try to return with the "head" of my linked list (which stores structures), some of the data is saved, but some is not. I have a function called linecutter. It should work fine according to my tests. The structure of the file is something like
for some reason the comment part returns correctly. If I printf the location data, it returns correctly, but otherwise it doesn't work as intended.
An examle of a file used:
Prog spec;2020/10/05;2020/11/01;00/00;23/59;Infoc;shouldnt forget it and leave to the last min
something;2020/10/05;2020/11/01;00/00;23/59;location;just a comment
asd asd;2020/2/02;2020/9/01;00/00;23/59;Infoc;lkasjd laksdj
This code should print the event names twice. Once when reading the file, once when checking in the main. But it only prints when reading.
#include <stdio.h>
#include <stdlib.h>
typedef struct Date{
int y;
int m;
int d;
} Date;
typedef struct Time{
int h;
int m;
} Time;
typedef struct Event{
char* name;
Date startdate;
Date enddate;
Time starttime;
Time endtime;
char* location;
char* comment;
} Event;
typedef struct Lista{
Event event;
struct Lista * next;
} Lista;
Date datecreate(char*todate)
{
Date *tmp = (Date *)malloc(sizeof(Date)*1);
int len = strlen(todate);
char date[len];
strcpy(date,todate);
char y[5];
char m[5];
char d[4];
int i =0;
for(; i<4; i++)
y[i] = date[i];
i++;
for(int var = 0; i<7; var++, i++)
{
m[var] = date[i];
}
i++;
for(int var = 0; i<10; var++, i++)
{
d[var] = date[i];
}
tmp->d = atoi(d);
tmp->m = atoi(m);
tmp->y = atoi(y);
return *tmp;
}
Time timecreator(char*totime)
{
Time tmp;
char h[3];
char m[3];
for(int i = 0; i<2; i++)
h[i] = totime[i];
for(int i = 4; i<6; i++)
m[i-4] = totime[i];
h[3] = '\0';
m[3] = '\0';
tmp.h = atoi(h);
tmp.m = atoi(m);
return tmp;
}
Event linecutter(char* line)
{
int i = -1;
int loc = 0;
char name[256], startdate[12],enddate[12],starttime[7],endtime[7],location[256],comment[512];
do{
i++;
name[i] = line[loc];
loc++;
}
while(name[i] !=';');
name[i] = '\0';
i=-1;
do{
i++;
startdate[i] = line[loc];
loc++;
}
while(startdate[i] !=';');
startdate[i] = '\0';
i=-1;
do{
i++;
enddate[i] = line[loc];
loc++;
}
while(enddate[i] !=';');
enddate[i] = '\0';
i=-1;
do{
i++;
starttime[i] = line[loc];
loc++;
}
while(starttime[i] !=';');
starttime[i] = '\0';
i=-1;
do{
i++;
endtime[i] = line[loc];
loc++;
}
while(endtime[i] !=';');
endtime[i] = '\0';
i=-1;
do{
i++;
location[i] = line[loc];
loc++;
}
while(location[i] !=';');
location[i] = '\0';
i=-1;
do{
i++;
comment[i] = line[loc];
loc++;
}
while(comment[i] !='\0');
comment[i] = '\0';
Event tmp;
tmp.name = name;
tmp.location = location;
tmp.comment = comment;
tmp.starttime = timecreator(starttime);
tmp.startdate = datecreate(startdate);
tmp.enddate = datecreate(enddate);
tmp.endtime = timecreator(endtime);
return tmp;
}
Lista * read(void)
{
FILE *fp;
char line[5000];
fp = fopen("esemenyek.txt" , "rw+");
if(fp == NULL) {
perror("error opening");
return NULL;
}
char buf[3];
fscanf(fp, "%3c", buf);
if (memcmp(buf, "\xEF\xBB\xBF", 3) != 0) //this is just for the encoding stuff
fseek(fp, 0, SEEK_SET);
/* ... handling the file ... */
Lista * head= NULL;
Lista * current = NULL;
while(fgets(line, sizeof(line), fp)!=NULL){
Lista *node = (Lista*)malloc(sizeof(Lista));
if(node == NULL)
{
perror("error");
return NULL;
}
node->event = linecutter(line);
node->next =NULL;
if(head== NULL){
current = head = node;
} else {
current = current->next= node;
}
for(int i = 0; i<500; i++)
line[i] ='\0';
printf("%s\n", current->event.name);
}
fclose(fp);
return head;
}
int main(void){
Lista * lst = read();
Lista *move;
for (move= lst; move!= NULL; move= move->next)
printf("%s\n", move->event.name);
return 0;
}
What am I doing wrong, or why is this not working? If someone could help me, I'd really appreciate it. I found another post here, it helped me to get here, but I don't know how to proceed from here.

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

How to find out what causes memory leak while freeing tree in C

I'm trying to find out which part of my code causes memory leaks.
To be more specific I already presume where it all begins but have no idea what to do to fix it.
These are my structures:
typedef struct {
char *suffix;
int occurr;
} suff_t;
typedef struct {
char **prefix;
suff_t **suffix;
int n_suff;
int cap_suff;
} data_t;
typedef struct node {
data_t *d;
struct node *left, *right;
} node_t, *tree_t;
And functions where I use malloc / realloc :
tree_t insert( tree_t t, char **buf, int ngram ) {
if( t == NULL ) {
node_t *n = malloc( sizeof *n);
n->d = create_data(buf, ngram);
n->left = n->right = NULL;
return n;
} else if( cmp_data( t->d, buf, ngram ) > 0 ) {
t->left = insert( t->left, buf, ngram);
return t;
} else if( cmp_data( t->d, buf, ngram ) < 0 ) {
t->right = insert( t->right, buf, ngram);
return t;
} else { // add suffix
insert_suffix(t->d, buf, ngram);
return t;
}
}
void insert_suffix(data_t *data, char **buf, int ngram) {
int i;
int cap;
for(i = 0; i < data->n_suff; i++) {
if( ! (strcmp(buf[ngram-1], data->suffix[i]->suffix)) ) {
data->suffix[i]->occurr++;
return;
}
}
if(data->n_suff == data->cap_suff){ // extend table of suffixes
cap = data->cap_suff;
data->suffix = realloc(data->suffix, 2*cap*sizeof*data->suffix); //
for(i = cap; i < 2*cap; i++)
data->suffix[i] = malloc(sizeof(suff_t));
data->cap_suff *= 2;
}
data->suffix[data->n_suff]->suffix = strdup(buf[ngram-1]);
data->suffix[data->n_suff]->occurr = 1;
data->n_suff++;
}
data_t * create_data(char **buf, int ngram) {
int i;
data_t *newdata = malloc(sizeof*newdata); //
newdata->prefix = malloc((ngram-1)*sizeof*newdata->prefix);
for(i = 0; i < ngram-1; i++) // copy prefix
newdata->prefix[i] = strdup(buf[i]);
newdata->suffix = malloc(8*sizeof*newdata->suffix);
for(i = 0; i < 8; i++)
//newdata->suffix[i] = malloc(sizeof*newdata->suffix[i]);
newdata->suffix[i] = calloc(sizeof*newdata->suffix[i], 1);
newdata->suffix[0]->suffix = strdup(buf[ngram-1]);
newdata->suffix[0]->occurr = 1;
newdata->n_suff = 1;
newdata->cap_suff = 8;
return newdata;
}
void free_data(data_t *d, int ngram) {
int i;
if(d == NULL) return;
printf("deleting data\n");
for(i = 0; i < ngram-1; i++)
free(d->prefix[i]);
free(d->prefix);
for(i = 0; i < d->cap_suff; i++) {
free(d->suffix[i]->suffix);
free(d->suffix[i]);
}
free(d->suffix);
free(d);
}
void free_tree(tree_t t, int ngram) {
if( t == NULL) return;
free_data(t->d, ngram);
free(t->left);
free(t->right);
printf("DELETING NODE\n");
free(t);
}
Valgrind prompts that something is wrong with function create_data and insert .
Please help
Valgrind is pointing to the place where the memory was allocated, not where you failed to release it.
The cuplrit is almost certainly free_tree. A tree is a recursive data-structure, which means you need to free it recursively. You are only freeing the root node.
Change these lines:
free(t->left);
free(t->right);
to
free_tree(t->left);
free_tree(t->right);
though I'm not sure what you'd provide as ngram. Probably pass in the original.
The point is that you have to navigate down each branch, freeing from the bottom up before releasing the node itself.

Hashing, linked list, delete node

My task is to delete a node from a array of pointers which point to structure.
My code doesn't work and I just don't know why:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Jmena4.h"
#define LENGTH 101
#define P 127
#define Q 31
typedef struct node {
char *name;
struct uzel *next;
} NODE;
int hash(const char Name[]) {
int i;
int n = strlen(Name);
int result;
result = Name[0] * P + Name[1] * Q + Name[n - 1] + n;
return result % LENGTH;
}
void Insert(NODE *array[], const char *name) {
NODE *u;
int h;
u = (NODE*)malloc(sizeof(NODE));
u->name = name;
h = hash(name);
u->next = array[h];
array[h] = u;
}
int Search(NODE *array[], const char *name) {
NODE *u;
u = array[hash(name)];
while (u != NULL) {
if (strcmp(u->name, name) == 0) {
printf("%s\n", u->name);
return 1;
}
u = u->next;
}
printf("Name: %s wasn't found\n", name);
return 0;
}
int Delete(NODE *array[], const char *name) {
NODE *current;
NODE *previous;
int position = hash(name);
current = array[position];
previous = NULL;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
if (previous == NULL) {
array[position] = current->next;
return 1;
} else {
previous->next = current->next;
current = NULL;
return 1;
}
}
previous = current;
current = current->next;
}
return 0;
}
int main() {
int i;
NODE *array[LENGTH];
for (i = 0; i < LENGTH; i++) {
array[i] = NULL;
}
for (i = 0; i < Pocet; i++) {
Insert(array, Jmena[i]);
}
for (i = 0; i < PocetZ; i++) {
Delete(array, JmenaZ[i]);
}
Search(array, "Julie");
system("PAUSE");
return 0;
}
EDIT 1: I changed names of variables and instead of position = array[position] should be current = array[position], but it still doesn't work.
EDIT 2 : In array Jmena is string "Julie" and I can search it after Insert function, but after I delete strings from JmenaZ which not included "Julie" program output is: Name: Julie wasn't found.
For one thing, current isn't initialized before it gets tested in the while loop.

Resources