Conditional jump or move depends on uniinitalized values - c

I am getting the following error from valgrind. Conditional jump or move depends on uninitalized values. I have looked around at similar questions but I am not able to find out whats wrong. I have initialized all the variables, but still..
unsigned long hash_word(const char *str)
{
unsigned long hash = 5381;
int c = 0;
while((c = *str)) // The error occurs here
{
hash = ((hash<<5) + hash) + c;
str++;
}
return hash%1999099;
}
The value of str is passed from the main function. I am using leak-check=full and track-origins=yes. Thanks in advance for the help.
First I am initializing a node.
typedef struct node{
char word[46];
struct node *next;
} node;
The calling code is
while(!(feof(fp)))
{
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
else
{
fscanf(fp,"%s",n->word);
index = hash_word(n->word);
.
.
. // further code
}

This looks like a misunderstanding in what feof() does. It doesn't return a true value until after a read has failed due to EOF. Therefore, in your last iteration, the fscanf() call fails and thus does not initialize n->word. You should check the return value of fscanf(). If it hits EOF it returns the C value EOF. You could also check for the value 1 indicating a single field was successfully converted.

Related

Seg Fault in C Hash Table implementation

I've been working on this dynamic memory allocator problem set where we must implement malloc and free and I was struggling a lot with the implementation of free. Outside of freeing the appropriate memory, there is a statistics struct that we must update with each call of malloc/free which holds a variable for the size of active allocations, active_size. To accurately update active_size the problem set says we should implement a hash table. I made the hash table to hold malloc pointers and the size of their allocations and I included a lookup_size function which would then be used in the free function to update the active_size. However, it seems the lookup_size functions is flawed and causes a seg fault at this line:
return tmp->payload;
I'll leave below the entire code as well in case anyone catches any other mistakes, but it would be a huge help if someone could figure out the cause of this seg fault. Thanks.
#define M61_DISABLE 1
#include "m61.hh"
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cinttypes>
#include <cassert>
// Hash table size
#define TABLE_SIZE 10
/// m61_malloc(sz, file, line)
/// Return a pointer to `sz` bytes of newly-allocated dynamic memory.
/// The memory is not initialized. If `sz == 0`, then m61_malloc must
/// return a unique, newly-allocated pointer value. The allocation
/// request was at location `file`:`line`.
static m61_statistics stat_count = {0, 0, 0, 0, 0, 0, 0, 4294967295};
// Hash table item defintion
typedef struct ht_item {
void* address;
unsigned long long payload;
struct ht_item* next;
} ht_item;
// Initialize hash table
ht_item* hash_table[TABLE_SIZE];
// Mod hash function
int hash_func(void* address) {
uintptr_t hash_value = (uintptr_t) address % TABLE_SIZE;
return hash_value;
}
// Empty hash table
void init_hash_table() {
for (int i = 0; i < TABLE_SIZE; i++) {
hash_table[i] = NULL;
}
}
// Hash table item insertion function
bool insert_item(ht_item* item) {
// Check if there actually is an item
if (item == NULL) {
return false;
}
// Insert item to front of the l_list (assign current val to next and new value to hash table)
int index = hash_func(item->address);
item->next = hash_table[index];
hash_table[index] = item;
return true;
}
// Hash table functiont that finds allocated sizes by mallocc
unsigned long long lookup_size(void* p) {
if (p == NULL) {
return 0;
}
int index = hash_func(p);
ht_item* tmp = hash_table[index];
while (tmp != NULL && tmp->address != p) {
tmp = tmp->next;
}
return tmp->payload;
}
void* m61_malloc(size_t sz, const char* file, long line) {
(void) file, (void) line; // avoid uninitialized variable warnings
// Your code here.
if (!base_malloc(sz)){
++stat_count.nfail;
stat_count.fail_size += sz;
}
else {
++stat_count.nactive;
++stat_count.ntotal;
stat_count.active_size += sz;
stat_count.total_size += sz;
init_hash_table();
void* p = base_malloc(sz);
ht_item* malloc_data = (ht_item*) malloc(sizeof(ht_item));
malloc_data->address = p;
malloc_data->payload = sz;
malloc_data->next = NULL;
insert_item(malloc_data);
}
return base_malloc(sz);
}
/// m61_free(ptr, file, line)
/// Free the memory space pointed to by `ptr`, which must have been
/// returned by a previous call to m61_malloc. If `ptr == NULL`,
/// does nothing. The free was called at location `file`:`line`.
void m61_free(void* ptr, const char* file, long line) {
(void) file, (void) line; // avoid uninitialized variable warnings
// Your code here.
if (ptr){
--stat_count.nactive;
stat_count.active_size -= lookup_size(ptr);
}
base_free(ptr);
}
Before getting into the answer, let me say this:
Dropping a chunk of memory management code on someone with no way to run it besides reverse-engineering the code from compiler output until it works is not nice.
Please, take a good look at this link before asking another question. https://stackoverflow.com/help/minimal-reproducible-example
So, you have this snippet of code:
while (tmp != NULL && tmp->address != p) {
tmp = tmp->next;
}
return tmp->payload;
Look at the loop condition:
while (tmp != NULL && tmp->address != p) { ... }
Assuming tmp->address never equals p, it keeps iterating as long as tmp is not NULL. In other words, it stops when tmp is NULL.
Then, in the very next line, you try to access tmp. But tmp is already NULL at that point! So you pretty much do this:
return NULL->payload;
And that's what causes the segmentation fault.
If this loop is meant to always succeed when free is called on a valid pointer, then you're probably not reliably calling insert_item in some case (in m61_malloc)?
Or, if insert_item should not be called on every call to m61_malloc, then you would not expect to find the item on every call to lookup_size, so you should check that tmp is not NULL after the loop. (you should probably do this regardless, because someone might call m61_free with an invalid pointer).
As for the cause of this bug, m61_malloc seems pretty fishy...
if (!base_malloc(sz)) {
...
} else {
...
void* p = base_malloc(sz);
...
}
return base_malloc(sz);
What do you expect this to do when the first call to base_malloc does not return NULL? As it stands, it goes into the 'else' branch, calls base_malloc a second time (either allocating again or returning a NULL that isn't handled), then calls base_malloc a third time in the return statement (again, possibly returning NULL).
In this scenario, the pointer that is stored in the hash table is the one that was returned by the second call to base_malloc, but the pointer that is returned (and that might be passed into m61_free later) is the one returned by the third call to base_malloc (which is NOT stored in the hash table).
Maybe this is the true cause of the error?
EDIT: changing m61_malloc as below fixes this particular segfault, though it's still wrong.
if (!base_malloc(sz)) {
...
return NULL;
} else {
...
void* p = base_malloc(sz);
...
return p;
}

read access violation variable

When i'm using char* pilih(char teks[]) in the int main() function, it's working. But when I used this function in the new function, it said read access violation. Please help me
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#define MAXARR 1000
char *hilangkan(char[]);
char *pilih(char[]);
char *loadFile(FILE *sumber);
int main(){
FILE *sumber;
sumber=fopen("kumpulan.txt","r");
char *teks=loadFile(sumber);
char *pilihan=pilih(teks);
printf("%s",pilihan);
printf("%s",hilangkan(pilihan));
}
char *hilangkan(char teks[]){
char *penghilangan;
strcpy(penghilangan,teks);
int y=strlen(penghilangan);
srand(time(NULL));
int c=48;
for(int i=0;i<y;i++){
int hilang=rand()%y+1;
penghilangan[hilang]='_';
}
return penghilangan;
}
char *loadFile(FILE *sumber){
char *teks;
if (sumber == NULL) {
printf("ERROR!!!");
system("pause");
return 0;
}
char h;
int count=0;
while (h = fgetc(sumber) != EOF) {
teks[count] = h;
count++;
}
fclose(sumber);
return teks;
}
char *pilih(char teks[]){
char *hasil;
srand(time(NULL));
int w = rand() % 47 + 1;
char cek[3];
itoa(w, cek, 10);
char *c=strstr(teks, cek);
int lokasi = c - teks + 1;
int pan = strlen(cek);
int i;
if (pan == 2)i = -1;
else i = 0;
while (teks[lokasi]!='\n') {
hasil[i] = teks[lokasi];
i++;
lokasi++;
}
hasil[i] = NULL;
return hasil;
}
On while(teks[lokasi]!='\n') it says read violation access. teks was 0x1110113
Links are highly discouraged and expectation from you is that, you should post the whole program in your question.
From the part of code that you have posted and the error information shared, it seems that the argument passed to pilih() function is not valid which in turn makes teks pointer pointing to some invalid memory. Actual cause of problem can only be given after looking at minimal, complete and verifiable program depicting the problematic behavior.
One confirm problem in your pilih() function is that you are returning a local variable hasil from it. The scope and life of local variable hasil is limited to pilih() function and it is no more valid once pilih() function exits.
Also, this statement
hasil[i] = NULL;
is not correct. Variable hasil is array of char and hasil[i] is a character at index i. You are assigning NULL to it which is not valid. I think you wanted to do this:
hasil[i] = '\0';
EDIT:
The full code has been posted in the question. Hence editing my answer and pointing out the problems in the OP's code.
There are several issues in your code. If you are using gcc compiler, try compiling your code with "-Wall -Wextra" options and check the warnings messages given by the compiler.
In the function loadFile(), look at this statement:
while (h = fgetc(sumber) != EOF) {
First of all, the return type of fgetc() function is int and not char [the fgetc() return type is int to accommodate for the special value EOF]. In the operator precedence table, the operator != comes before =, so you will not get the read character assigned to h but the result of fgetc(sumber) != EOF will be assigned to h. This should be
while ((h = fgetc(sumber)) != EOF) { // check the parenthesis added
^ ^
In this statement:
teks[count] = h;
You are accessing a pointer which is not initialized. Any variable which is not initialized has indeterminate value and same is true for pointers. They can point to any random indeterminate address. There is no default behavior. Only behavior is indeterminate and using indeterminate values results in Undefined behavior.
You should allocate memory to teks before using it, like this:
teks = malloc(100 * sizeof (char)); //this will allocate memory for 100 characters.
if (teks == NULL)
exit(EXIT_FAILURE);
Looks like you want to store the whole file content in teks. Make sure to allocate enough memory to teks and if you are not sure about the size of memory required then realloc is your friend.
Also, after while loop, you should add the terminating null character at the end of the content stored in teks, like this:
teks[count] = '\0';
The same error of accessing uninitialized pointer exists in hilangkan() and pilih() function. Check the variable penghilangan and hasil respectively.
strstr() can return NULL pointer. You should add check for it:
char *c=strstr(teks, cek);
if (c == NULL)
return NULL; // Or whatever the way you want to handle this case
// but you should not use c
You should check the parameter value before using it in every function. If it is pointer, check whether it is NULL or not. If it is not NULL then only use it.
Also, make sure to free the dynamically allocated memory once you are done with it.
I don't what exactly you are trying to do but somewhere I feel that there is lot of scope of improvements in your code.
Hope this help.

How to fix a condition error from a string array

So I declared an array of strings as
typedef char String[11]; and in my main function I have this condition
`
char word[12];
String hashArray[SIZE];
if (insertword(word, hashArray) == 1)
printf("word %s successfully inserted.\n", word);
This is the function that it calls.
int insertword(char word[], String hashArray[])
{
//get the hash
int hashIndex = hashfunction1(word)% 7 ;
printf("INDEX:%d\n", hashIndex); //delete later
if (hashArray[hashIndex] == NULL) //ERROR IS HERE
{
strcpy(hashArray[hashIndex], word);
printf("INSERTED!! ");
return 1;
}
else
{
printf("NOT INSERTED!! ");
return 0;
}
}
I have tested my program by adding a print and apparently the error happens at the first conditional statement. The else part is always what gets executed. I'm definitely missing something here, any help would be appreciated.
The problem with your code:
char word[12];
String hashArray[SIZE];
word is not initialized, hence it has garbage values.
Then inside insertword function:
int hashIndex = hashfunction1(word)% 7;
The array "decays" into a pointer to the first element:
hashfunction1(word)%7;
Is just as:
hashfunction1(word[0])%7;
When again, word is not initialized, so the value will be put in hashIndex is unknown!
Then you are accessing the array hashArray[hashIndex] in that index which is unknown, might be out of boundary.
Accessing an array outside its bounds has "undefined behavior".
To fix this, you need to put some random values in word array which will be smaller than 32, as stated in your comment, size = 32.

Trie Implementation in C: Segmentation Fault

I'm currently doing CS50 from Harvard and the goal is it to load a dictionary into any data structure in the fastest way possible. For this problem set I'm using a Trie.
The logic behind my code is as follows:
Read one character at a time.
Check in the childnode of the trie if the character already exists, if it equals NULL, we allocate some space to it.
The curser is set to the childnode we just allocated space to.
If we reach the end of a word ("\n") we set the boolean value to true and completely reset the curser to its initial value (which we have stored previously in the curser->root).
I have tried several implementations, some of them had a few logical errors which I was not happy with and some gave me segmentation faults when I had a big dictionary.
Below is the code of my latest implementation, basically what happens is that it's fine with loading the first word into the trie structure, but it fails at the second. The problem then lays into me setting the new node value to the childenode (to which we allocated some free space). The logic behind this is it to obviously connect the tree and move on to the next node. This is the code which I think is wrong:
curser = curser->children[tolower(ch) - 'a'];
But the thing is, it worked in some of my other implementations, only with this one it stopped working all of a sudden and gave me a segmentation fault after the first word. As I said, I'm a beginner in coding so please enlighten me and criticize my implementation! Thanks a bunch.
#include <stdbool.h>
#include <stdio.h>
#include "dictionary.h"
#include <ctype.h>
#include <stdlib.h>
typedef struct node
{
bool end;
struct node* children[27];
struct node* root;
struct node* next;
} node;
//global variable used to check the number of words in the trie
int totalwords = 0;
//root node
node* curser;
int ch;
int main(void)
{
FILE* dict = fopen("text.txt", "r");
if (dict == NULL)
{
printf("Could not open dictionary\n");
return 1;
}
curser = (struct node*) malloc(sizeof(node));
curser->root = curser;
for (ch = fgetc(dict); ch != EOF; ch = fgetc(dict))
{
if (ch == '\0')
{
curser->end = true;
curser = curser->root;
totalwords++;
printf("%i\n", totalwords);
}
else
{
if (isalpha(ch))
{
if (curser->children[tolower(ch) - 'a'] == NULL)
{
curser->children[tolower(ch) - 'a'] = (struct node*)malloc(sizeof(node));
}
curser = curser->children[tolower(ch) - 'a'];
}
else if (ch == '\'')
{
if (curser->children[26] == NULL)
{
curser->children[26] = (struct node*)malloc(sizeof(node));
}
curser = curser->children[26];
}
}
}
fclose(dict);
return false;
}
Edit:
Another question I have is why my in my current code it is not able to detect the Null Terminator \0 but it can detect a new line \n? I need to be able to detect the null terminator in order to get the correct amount of words. Any suggestion as to what is wrong?
After curser->root=curser; You should do the following:
curser->end=false;
curser->next=NULL;
for(i=0;i<27;i++)
curser->children[i]=NULL;
When you initialize memory for curser it is not guaranteed that it's members will be automatically allocated to NULL and false.
Do this everywhere for a node you are allocating memory dynamically.
You also need to set child->root=curser->root for every children you are allocating memory dynamically
It looks as if this relates to Pset5 of CS50, and you are trying to implement the loading of a dictionary. As it happens, you are using the fgetc function to read a single letter from a text file, and not from memory.
When you are reading from memory, there will be a '\0' NULL terminator for the word. However, with fgetc you are using stdio to read from the file and the '\0' terminator does not exist in that file. Since the words in the CS50 dictionary are stored one word per line, and all lines end with a '\n' ("new line"), it can be found that way.

Problem using strstr function

I'm having trouble using strstr. Here's what I have:
Passing character array of length 21 bytes to a function.
Traversing through nodes of a linked list, comparing each node's character array with the above array passed as mentioned in point 1
strstr is always returning NULL irrespective of any string passed
Let's say for example code like strstr("hello","he"). It should return pointer to "hello", but that never happens in my code below. It is always returns NULL.
Here is the code snippet of the program:
void display_to_file(const char *chr,c_uint32 pos_in_list,c_uint32 line_no)
{
NODE *search = ptrs_to_heads_of_alpha[pos_in_list];
char *chk;
char redundant[21]={'\0'};
int first=1;
uint32 count = 0;
while((NULL!=search) && (count<21))
{
printf("\nsearch->arg=%s",search->arg); /*for example search->arg is "hello"*/
/*above statement prints "hello"-correctly*/
/*for example chr="?he" */
printf("\nchr=%s",&chr[1]); /*prints "he" correctly*/
chk=strstr(search->arg,&chr[1]);
if(chk != NULL) /*is always null- not known why it returns null even for valid cases*/
{
printf("\nentered_\n");
++count;
if(1 == first)
{
fprintf(op_fp," %s\n",search->arg);
strcpy(redundant,search->arg);
printf("\nop:%s\n",search->arg);
first = 0; /*only for first node print*/
}
else
{
if(strcmp(redundant,search->arg) == 0)/*duplicate found*/
--count; /*need to search for one more item*/
else
{
fprintf(op_fp," %s\n",search->arg);
strcpy(redundant,search->arg);
}
}
}
else
printf("\nelse,else,else\n\n"); /*Always this statement is executed even
if I passed valid arguments*/
search=search->next;
}
}
is there any warning with this statement at compile time?:
chk=strstr(search->arg,&chr[1]);
2nd argument should be const char * in strstr()
make sure this thing.
One more thing try with this statement
chk=strstr(search->arg,"he");
one more thing check you have included string.h
#include<string.h>
Try embracing string with quotes (or another noticeable symbol), because there could be space characters, for example, which you don't see. So replace
printf("%s\n", some_string);
with
printf("\"%s\"\n", some_string);
I recommend to always use embracing with "printf-debugging". However, your problem could be somewhere else. Try to shorten your program for finding an error.

Resources