Not sure where there is an unitialized value created by heap allocation - c

Everything seems to be working fine, memory is allocating and freeing and doing what its supposed to be doing but when I check it with valgrind --track-origins=yes I get this conditional jump after entering in a name and a number.
==25590== Conditional jump or move depends on uninitialised value(s)
==25590== at 0x4007BD: add_car (in /students/5/gmi6y5/cs2050/lab4/a.out)
==25590== by 0x400704: main (in /students/5/gmi6y5/cs2050/lab4/a.out)
==25590== Uninitialised value was created by a heap allocation
==25590== at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==25590== by 0x4006D9: main (in /students/5/gmi6y5/cs2050/lab4/a.out)
typedef struct FreightCars_
{
char *name;
int number;
struct FreightCars_ *next_car;
}FreightCar;
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Insufficient number of arguements\n");
return 0;
}
int size = atoi(argv[1]);
FreightCar *engine = (FreightCar*)malloc(sizeof(FreightCar));
int i;
for(i=0;i<size;i++)
{
printf("Enter in freight car name and number: ");
add_car(engine);
}
free_cars(engine);
return 0;
}
void add_car(FreightCar *engine)
{
FreightCar *newPtr = (FreightCar*)malloc(sizeof(FreightCar));
newPtr->name = malloc(sizeof(char) * MAX_STR_LEN);
if(newPtr == NULL)
{
printf("Unable to allocate memory\n");
exit(1);
}
scanf("%s", newPtr->name);
scanf("%d", &newPtr->number);
newPtr->next_car = NULL;
if(engine->next_car == NULL)
{
engine->next_car = newPtr;
printf("added at the beginning\n");
}
else
{
FreightCar *currentPtr = engine;
while(currentPtr->next_car != NULL)
{
currentPtr = currentPtr->next_car;
}
currentPtr->next_car = newPtr;
printf("added later\n");
}
free(newPtr->name);
}
void free_cars(FreightCar *engine)
{
if(engine == NULL)
{
printf("Linked list is empty now\n");
}
else
{
free_cars(engine->next_car);
}
free(engine);
engine = NULL;
}

In main you do
FreightCar *engine = (FreightCar*)malloc(sizeof(FreightCar));
then in a for loop you call
add_car(engine);
add_car does
if(engine->next_car == NULL)
But as #Oli Charlesworth pointed out in a comment, you have not initialised the memory pointed to by engine, so you are making a decision based on unitialised memory contents here, hence the Valgrind complaint.

Related

Valgrind: Conditional jump or move depends on uninitialised value(s). Is not terminating a string inside a longer array with '\0' enough?

The problem set 5 of cs50, speller, ask to implement some dictionary functionalities.
I get this warnings with valgrind:
==393== Conditional jump or move depends on uninitialised value(s)
==393== at 0x49DB143: tolower (ctype.c:46)
==393== by 0x483F864: strcasecmp (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==393== by 0x4019CF: check (dictionary.c:42)
==393== by 0x401603: main (speller.c:114)
==393== Uninitialised value was created by a heap allocation
==393== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==393== by 0x401AF8: load (dictionary.c:82)
==393== by 0x40129E: main (speller.c:40).
Here it is my dictionary.c file, which contains the helpers function.
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dictionary.h"
#include <strings.h>
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = 1;
unsigned int siz = 0;
// Hash table
node *table[N];
/*
for (int i = 0; i < N; i++)
{
table[i]->next
}
*/
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
int h = hash(word);
node *ll = table[h];
while (ll != NULL)
{
if (strcasecmp(ll->word, word) == 0)
{
printf("len: %lu\n", strlen(ll->word));
return true;
}
ll = ll->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO
return 0;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
printf("a\n");
// TODO
FILE *input = fopen(dictionary, "r");
if (input == NULL)
{
printf("Could not open file.\n");
return false;
}
printf("b\n");
char c;
int i = 0;
unsigned int h = 0;
char word[LENGTH + 1];
node *key = NULL;
while (fread(&c, sizeof(char), 1, input))
{
if (i == 0)
{
key = malloc(sizeof(node));
}
else if (c == '\n')
{
word[i] = '\0';
i = 0;
h = hash(word);
key->next = table[h];
table[h] = key;
siz++;
continue;
}
key->word[i] = c;
i++;
}
fclose(input);
/*
for (int j = 0; j < N; j++)
{
while (table[j] != NULL)
{
printf("%s ->\n", table[j]->word);
table[j] = table[j]->next;
}
}
*/
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO
return siz;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
node *n = NULL;
node *tmp = NULL;
for (int i = 0; i < N; i++)
{
n = table[i];
while (n != NULL)
{
tmp = n;
n = n->next;
free(tmp);
}
}
return true;
}
I think this warning happens because at line 42 the function strcasecmp is trying to lowercase some characters of the string node->word, even after the '\0'.
In fact, the warnings go away if I substitute, in load(),
key = malloc(sizeof(node)); with key = calloc(1, sizeof(node));
Because calloc allocate and also sets the memory to 0.
So, my question is: how strcasecmp really work??
In the malloc scenario ll->word, the argument I pass to strcasecmp, is an array of chars like this "actual_valid_chars \0 garbage bytes until array length: LENGTH".
In the calloc scenario the array is "actual_valid_chars \0 000000...".
So, I think that at I am passing uninitialized memory to strcasecmp, in case of malloc, but I also terminate the string with \0 in both scenarios.
Shouldn't strcasecmp() recognize the end of the string by '\0' even if it is in the middle of the array?
Can someone clarify these passages to me please?
Also, can I simply ignore these warnings, or are there better practices to use?
key->word is not null terminated in the load function. The char array word is, though it's never populated.

Deallocated memory functions C

I have problems with memory deallocation in C. Without the division of functions everything is OK, but unfortunately it does not work on the same functions. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct {
char *name;
enum {
summer,
winter
} index;
} student;
bool init(student *s) {
printf("The next stage in the allocation of memory\n");
s = (student*)malloc(sizeof(*s));
if (&s == NULL) {
printf("Allocation Failed\n");
return 0;
} else {
printf("Allocation completed successfully\n");
}
}
void delete(student *s) {
if (&s != NULL) {
printf("begin removal\n");
free(s);
printf("Released memory");
}
}
int main() {
student *s;
init(s);
delete(s);
return 0;
}
I do not know what I'm doing wrong. Please help.
First of all the function init has undefined bbehaviour because it returns nothing in the case of successful memory allocation.
You can check whether the memory was allocated or not by returning pointer to the allocated memory or NULL.
Also this statement
if(&s==NULL){
is wrong. The condition will always yield false because the address of the local variable s is not equal to NULL.
So the function can be rewritten either the following way
student * init()
{
printf("The next stage in the allocation of memory\n");
student *s = ( student* )malloc( sizeof( *s ) );
if ( s == NULL )
{
printf("Allocation Failed\n");
}
else
{
printf("Allocation completed successfully\n");
}
return s;
}
And called like
int main( void )
^^^^^
{
student *s = init();
//...
Or it can be defined the following way
int init( student **s )
{
printf("The next stage in the allocation of memory\n");
*s = ( student* )malloc( sizeof( **s ) );
int success = *s != NULL;
if ( !success )
{
printf("Allocation Failed\n");
}
else
{
printf("Allocation completed successfully\n");
}
return success;
}
and called like
int main( void )
^^^^^
{
student *s;
init( &s );
//...
The function delete should be defined at least like
void delete(student *s) {
if (s != NULL) {
^^^
printf("begin removal\n");
free(s);
printf("Released memory");
}
}
Firstly, free is NULL safe. If variable is NULL already, basically nothing happens. You do not have to check if it is NULL. (you can check page 313 ISO-IEC 9899 )
Also, when you initialize student->name and allocate, there will be memory leak. You have to free that too.
So, your delete function could be like this ;
void delete(student *s) {
printf("begin removal\n");
free(s->name);
free(s);
printf("Released memory");
}
And if (&s == NULL) is wrong. They must be changed with if (s == NULL).
Your allocation may cause really big troubles in the big codes. If you allocate s = (student*)malloc(sizeof(*s)); it means that "allocate s with size of *s". But pointer size is fixed memory block (mostly 8 bytes). It means that you blocks certain size of memory. If you have bigger struct than that, this kind of allocation will corrupt the memory and your executable will be killed by the OS(you can try add some more variables to your struct and initialize them). In small structs and very short runtimes, mostly this allocation works too. But i guarantee that this is not safe for run-time. And it will not give any warnings or errors in compile-time. True way is s = malloc(sizeof(student)). With this way, you exactly allocates all the memory blocks. And your memory stay safe in run-time.
Lastly, your init function should return the initialized variable. And your init function could be like this ;
#define NAME_LENGHT 128
...
student * init(student *s) {
printf("The next stage in the allocation of memory\n");
s = malloc(sizeof(student));
if (s == NULL) {
printf("Allocation Failed\n");
return NULL;
}
s->name = malloc(NAME_LENGHT);
if (s->name == NULL) {
printf("Allocation Failed\n");
return NULL;
} else {
printf("Allocation completed successfully\n");
}
//alternatively you can strdup directly without any allocation
// s->name = strdup("some name");
return s;
}
You never change the s in main.
Solution 1: Pass a pointer to the variable in main for init to populate.
void init_student(student** s_ptr) {
*s_ptr = (student*)malloc(sizeof(student));
if (*s_ptr == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
(*s_ptr)->name = malloc(MAX_NAME_SIZE + 1);
if ((*s_ptr)->name == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
(*s_ptr)->name[0] = 0;
(*s_ptr)->gpa = 0;
}
void delete_student(student* s) {
free(s->name);
free(s);
}
int main() {
student* s;
init_student(&s);
delete_student(s);
return 0;
}
Solution 1b: Same, but a cleaner implementation.
void init_student(student** s_ptr) {
student* s = (student*)malloc(sizeof(student));
if (*s_ptr == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
s->name = malloc(MAX_NAME_SIZE + 1);
if (s->name == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
s->name[0] = 0;
s->gpa = 0;
*s_ptr = s;
}
void delete_student(student* s) {
free(s->name);
free(s);
}
int main() {
student* s;
init_student(&s);
delete_student(s);
return 0;
}
Solution 2: Return the allocated point to main.
student* init_student() {
student* s = (student*)malloc(sizeof(student));
if (s == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
s->name = malloc(MAX_NAME_SIZE + 1);
if (s->name == NULL) {
fprintf(stderr "panic: Allocation Failed\n");
exit(1);
}
s->name[0] = 0;
s->gpa = 0;
return s;
}
void delete_student(student* s) {
free(s->name);
free(s);
}
int main() {
student* s = init_student();
delete_student(s);
return 0;
}
Note that &s == NULL will never be true because &s is the address of the variable itself. You want just s == NULL to check the value of the pointer in s.

creating own malloc function in c

I have create my own malloc function and it works properly. but I want to create another malloc using only array without struct. Is that possible to create without struct? This is my code.
#include <stdio.h>
char memory[20000];
int freeMem=20000;
typedef struct{
int start;
int end;
}chunk;
void *MyMalloc(int size){
printf("\nMemory Size= %d ",size);
if(size==0){
printf("0 means no memory\n");
return 0;
}
int memsize=20000;
chunk *p=(chunk *)&memory[0];
if(freeMem >= size+sizeof(chunk)){
while(p<(chunk *)&memory[19999]){
if(p->start==0){
if(p->end !=0){
if(size+sizeof(chunk)< (p->end - (int)p)){
p->start=(int)p+8;
p->end=(int)p+8+size;
freeMem = freeMem-(size+8);
printf("free Mem : %d\n",freeMem);
return (int *)p->start;
}
else{
p=(chunk *)p->end;
continue;
}
}
else{
p->start=(int)p+8;
p->end=(int)p+8+size;
freeMem = freeMem-(size+8);
printf("free Mem : %d\n",freeMem);
return (int *)p->start;
}
}
p = (chunk *)p->end;
}
}
else{
printf("no space...!\n");
return 0;
}
}
void MyFree(void * p){
chunk *ptr = (chunk *)p;
ptr--;
freeMem=freeMem+(ptr->end - ptr->start)+sizeof(chunk);
if(ptr->start != 0){
printf("\nfreed Memory : %d\t",ptr->end - ptr->start);
ptr->start = 0;
}
else{
printf("\nno Such memory allocated!!!!!\n");
}
}
Roughly speaking, the basic mechanism to use would be the same. In MyMalloc, allocate 2*sizeof(int) space more, store the content of a chunk there and return the address behind the 2*sizeof(int). On deallocation, do the same process in reverse - subtract 2*sizeof(int) from the argument to access the content of which was stored in chunk before.

Using malloc in function?

I am new to malloc. So I wanted to test this small code.
I'm getting the "segmentation fault error".
**EDIT: The problem was from not allocation char* name (Thanks to #Zack)
You can see what caused the problem:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct info { char *name; } fileinfo;
void mal (fileinfo **ptr)
{
if ((*ptr = (fileinfo*) malloc(3*sizeof(fileinfo))) == NULL) {
fprintf(stderr,"Memory allocating error #1\n");
exit(1);
}
//that what was causing the error - START
for (j = 0; j < 3; j += 1)
{
(*ptr)[j].name = (char*) malloc(10*sizeof(char*));
}
//that what was causing the error - END
strcpy(ptr[0]->name,"1. A\n"); //line 13
strcpy(ptr[1]->name,"2. B\n");
strcpy(ptr[2]->name,"3. C\n");
}
int main (int argc, char *argv[])
{
fileinfo *files;
int i;
mal(&files); //line 22
for (i = 0; i < 3; i += 1)
{
printf("name=%s\n",files[i].name);
}
free(files);
return 0;
}
Using valgrind:
==5751== Use of uninitialised value of size 8
==5751== at 0x4006EB: mal (mal1.c:13)
==5751== by 0x400747: main (mal1.c:22)
==5751==
==5751== Invalid write of size 4
==5751== at 0x4006EB: mal (mal1.c:13)
==5751== by 0x400747: main (mal1.c:22)
==5751== Address 0x0 is not stack'd, malloc'd or (recently) free'd
What am I doing wrong??!
Thanks in advance.
Your problem is that you need to allocate ptr[i]->name before copying to it. A pointer by itself points to some random area of memory. To use it, you must get good memory that is safe and that is what malloc and calloc, and (new in C++) all do. The example you gave is still a mess, and my correction isn't that great, but you get the idea that every pointer in C and C++ must be allocated from somewhere. And, on the flipside, once you are done with the pointer, you have to free them.
void mal (fileinfo **ptr, int count)
{
if ((*ptr = (fileinfo*) malloc(count*sizeof(fileinfo))) == NULL) {
fprintf(stderr,"Memory allocating error #1\n");
exit(1);
}
for (int i = 0; i < 3; i++) {
char buff[2];
buff[0] = 'A' + i;
buff[1] = 0;
ptr[i]->name = malloc( 10 );
strcpy(ptr[0]->name,"1. %s\n", buff);
}
}
Try with
void mal (fileinfo **ptr) {
if ((*ptr = malloc(3*sizeof(fileinfo))) == NULL) {
perror("Memory allocating error #1\n");
exit(EXIT_FAILURE);
}
if (!(ptr[0]->name = strdup("1. A\n")))
{ perror("string 1"); exit(EXIT_FAILURE);};
if (!(ptr[1]->name = strdup("2. B\n")))
{ perror("string 2"); exit(EXIT_FAILURE);};
if (!(ptr[2]->name = strdup("3. C\n")))
{ perror("string 3"); exit(EXIT_FAILURE);} ;
}
BTW, it would be better to make it a function returning a pointer, like
fileinfo* make() {
fileinfo* ptr = malloc(3*sizeof(fileinfo)));
if (!ptr) { perror("make fileinfo"); exit(EXIT_FAILURE); };
if (!(ptr[0]->name = strdup("1. A\n")))
{ perror("string 1"); exit(EXIT_FAILURE);};
if (!(ptr[1]->name = strdup("2. B\n")))
{ perror("string 2"); exit(EXIT_FAILURE);};
if (!(ptr[2]->name = strdup("3. C\n")))
{ perror("string 3"); exit(EXIT_FAILURE);} ;
return ptr;
}
Then, you need a destructor function like
void destroy(fileinfo*ptr) {
free (ptr[0]->name);
free (ptr[1]->name);
free (ptr[2]->name);
free (ptr);
}
to be called instead of your free at the end of your main
Notice that your code is very ad hoc: the number (i.e. 3) of names is completely built-in. This is wrong design. At the very least, that constant should have been named:
#define NB_FILES 3
Actually, a much better approach would be to declare your structure with a flexible array member:
typedef struct fileinfo_st {
unsigned nbfiles;
char* filenames[];
} Fileinfo;
See this for more. You could even have a variadic function to make such structures.
FIleinfo *make(int, ...);
Which you would call like
Fileinfo* ptr = make (3, "abc","def","ghijklmnop");
or you could decide that that last variadic argument is NULL
BTW, read about undefined behavior. You might be unlucky to have your program not crashing but still be very wrong. And compile with gcc -Wall -g and learn more how to use the gdb debugger and valgrind

Problems concerning pointers and malloc in C90

I am quite a newbie when it comes to C, and seem to be having a few issues when it comes to memory allocation and pointers. For my assignment, we have to create the ADT of dynamic sets using arrays, and to do this we require heavy use of pointers which I find a bit difficult to grasp.
I created a structure to act as the sets
struct Set{
int arrelement; //the 'size' of the array
int * arrvalue;; //the array
}
typedef struct Set *SetArray;
The issue arises when I come to applying functions such as Add(where I add a unique element to the set) or Cardinality (where the programs shows me the total number of elements in the set). Adding seems to crash my program after more than 2 additions and trying to retrieve the stored data supplies junk variables.
Here is the code for the relevant functions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Array.h"
int size = 1; // similar to arrelement, to be used for realloc
SetArray Create(){ // to allocate memory for the set
SetArray sptr;
sptr = malloc(sizeof(struct Set));
sptr->arrvalue = malloc(sizeof(struct Set));
sptr->arrelement = 1;
return sptr;
}
SetArray Add(SetArray sptr, int x){
if(Is_Element_Of(x, sptr)){ //function to keep elements in set unique.
//Function works, which brings me to
//believe values are being stored
puts("Value already exists, enter a unique value");
}
else{
if(sptr == NULL){
puts("Memory Allocation Failed. Shutting down.");
exit(EXIT_FAILURE);
}
}
sptr = realloc(sptr, size*sizeof(struct Set)); //reallocate memory
//for the
//new element
sptr->arrvalue[sptr->arrelement] = x;
sptr->arrelement++;
size++;
return sptr;
}
SetArray Remove(SetArray sptr, int x){
if(sptr == NULL){
puts("Memory Allocation Failed. Shutting down.");
exit(EXIT_FAILURE);
}
else if(!Is_Element_Of(x, sptr)){
puts("Value is not in set");
}
else if(sptr->arrvalue == NULL){
puts("Set is empty. Cannot remove that which does not exist");
}
else{
sptr = realloc(sptr, size*sizeof(struct Set));
sptr->arrvalue[sptr->arrelement] = '\0';
sptr->arrelement--;
size--;
}
return sptr;
}
SetArray Clear(SetArray sptr){
if(sptr == NULL){
puts("Memory Allocation Failed. Shutting down.");
exit(EXIT_FAILURE);
}
int i;
for(i = 0; i < sptr->arrelement; i++){
sptr->arrvalue[i] = '\0';
}
return sptr;
}
Also, not sure if relevant, but just in case, here is the Function Is_Element_Of
int Is_Element_Of(int x, SetArray sptr){
if(sptr == NULL){
puts("Memory Allocation Failed. Shutting down.");
exit(EXIT_FAILURE);
}
int flag = 0;
int i;
for(i = 0; i < sptr->arrelement; i++){
if(sptr->arrvalue[i] == x){
flag = 1;
}
}
return flag;
}
Pardon me for any mistakes, but this is my first time asking and I tried my best to keep everything organized and structured properly.
Thank you for reading.
You are reallocating the wrong pointer you realloc the pointer to your parent Set when you want to realloc the array it contains.
sptr = realloc(sptr, size*sizeof(struct Set));
should be
sptr->arrvalue = realloc(sptr->arrvalue, (sptr->arrelement+1)*sizeof(int));
I guess your main problem is this :
sptr->arrvalue = malloc(sizeof(struct Set));
since arravlue is int*, try this :
sptr->arrvalue = malloc(sizeof(int));
edit: same for realloc

Resources