1

char *string = (char *) malloc(sizeof(char) * sz);

code right before this->void insert_word(word *root, char string1[], int linenumber) { int sz=strlen(string1)<=MAX_WORD_LENGTH?strlen(string1):MAX_WORD_LENGTH; Code block 3 has the entire context

Sometimes malloc() returns a populated memory location while using it.

What bothers me is that this is not random. (This program consists of taking words from a file and passing them to this function. For THE SAME WORD, the function behaviour(in particular that of malloc()) is different.

For the inputs string1=0x7fffffffdf10 "lol" root=BST, sz gets a value of 3

The value allocated to string by malloc() is 0x55555555c510 "\340\305UUUU" Why is malloc not pointing to an empty memory location? (This is not random behaviour, it is predictable and repeatable) Furthermore,this loop runs an infinite amount of time for some reason

while(strcmp(string1,string)!=0)
    {
        free(string);
        string=NULL;
        string = (char *) malloc(sizeof(char) * sz);
        strncpy(string,string1,sz);
    }

MORE RELAVANT CODE

  1. #define MAX_WORD_LENGTH 20

  2. Definition of the structures

    typedef struct linkedList
        {
            int number;
            struct linkedList *next;
        }list;
        typedef struct word_with_count
        {
            char* string;
            list *linenumbers;
            struct word_with_count *left;
            struct word_with_count *right;
        }word;```
    

[3] ) The function

void insert_word(word *root, char string1[], int linenumber) {
    int sz=strlen(string1)<=MAX_WORD_LENGTH?strlen(string1):MAX_WORD_LENGTH;
    char *string = (char *) malloc(sizeof(char) * sz);
    strncpy(string,string1,sz);
    if (root==NULL) {
        return;
    } else if (strcmp(string, root->string) < 0) {
        if (root->left == NULL) {
            root->left = createword(string, linenumber);
        } else {
            insert_word(root->left, string, linenumber);
        }
    } else if (strcmp(string, root->string) > 0) {
        if (root->right == NULL) {
            root->right = createword(string, linenumber);
        } else {
            insert_word(root->right, string, linenumber);
        }
    } else {
        append_list(linenumber, root->linenumbers);
    }
    free(string);
}
  1. main() which calls this function
int main() {
    char path[MAX_PATH_LENGTH];
    FILE *fp;
    fgets(path, MAX_PATH_LENGTH, stdin);

    if (strlen(path) > 0 && path[strlen(path) - 1] == '\n')
        path[strlen(path) - 1] = '\0';
    
    fp = fopen(path, "r");
    if (fp == NULL) {
        printf("File not found\n");
        return 0;
    }
    char ch;
    int line_count = 1;
    char current_word[MAX_WORD_LENGTH] = "";

    word *root = NULL;
    while (!feof(fp)) {
        ch = fgetc(fp);
        //printf("%c", ch);

        if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') {
            if (ch >= 'A' && ch <= 'Z')
                ch = ch - 'A' + 'a';

            strncat(current_word, &ch, 1);
        } else if (ch == '-') {
            continue;
        } else {
            if (strlen(current_word) > 2) {
                if (root == NULL) {
                    root = createword(current_word, line_count);
                } else {
                    insert_word(root, current_word, line_count);
                }
            }
            memset(current_word, 0, sizeof(current_word));
            if (ch == '\n') {
                line_count++;
            }
        }
    }
    if (strlen(current_word) > 2) {
        if (root == NULL) {
            root = createword(current_word, line_count);
        } else {
            insert_word(root, current_word, line_count);
        }
    }
    fclose(fp);
    // print_tree(root);
    //printf("\n");
    //print_tree(root);
    int status=delete_low_ocurrence(root, NULL, 3);
    if (status == -1)root = NULL;
    print_tree(root);
    freetree(root);
    return 0;
}

5)Auxilary function used by this function

word* createword(char string[], int linenumber)
{
    word *newword = (word*)malloc(sizeof(word));
    int sz=strlen(string)<=MAX_WORD_LENGTH?strlen(string):MAX_WORD_LENGTH;
    newword->string = (char*)malloc(sizeof(char)*sz);
    strncpy(newword->string, string,sz);
    newword->linenumbers = (list*)malloc(sizeof(list));
    newword->linenumbers->number = linenumber;
    newword->linenumbers->next = NULL;
    newword->left = NULL;
    newword->right = NULL;
    return newword;
}
  1. Textfile given as input
much2f
much3f
lol
lol
lol
qwertyuiopasdfghjklzxcvbnmqwertyuiop
qwertyuiopasdfghjklzxcvbnmqwertyuiop
qwertyuiopasdfghjklzxcvbnmqwertyuiop
qwertyuiopasdfghjklzxcvbnmqwertyuiop
trincot
  • 317,000
  • 35
  • 244
  • 286
  • 1
    There is no such thing as empty memory. Think about a byte as eight switches that can be flipped up or down, like light switches. If the switches are all down, that encodes 0, if they are all up, that is 255. What would it mean for these switches to be “empty”? The switches are never gone or invisible. They are always there, each one in an up or down position. There is no empty memory. – Eric Postpischil Feb 28 '22 at 16:04

2 Answers2

2

Why is malloc not pointing to an empty memory location?

Because it can. The content of the allocated memory via malloc() is not specified.

If code needs zeroed out memory, see calloc().


Bad code

strncpy(string,string1,sz) does not result in string being a string as it may lack null character termination. The following (strcmp(string... is then undefined behavior. Instead, do not use strncpy(), use strcpy() and make certain the prior allocation has enough room for the terminating null character.

strncpy(string,string1,sz);
...
} else if (strcmp(string, root->string) < 0) { // bad

Repaired code

word* createword(const char string[], int linenumber) {
  word *newword = calloc(1, sizeof *newword);
  size_t length = strlen(string);
  if (length > MAX_WORD_LENGTH) {
    length = MAX_WORD_LENGTH;
  }
  char *s = malloc(length + 1); // Include room for the \0
  list *linenumbers = calloc(1, sizeof *linenumbers);
  // Test allocation success
  if (newword == NULL || s == NULL || linenumbers == NULL) {
    free(newword);
    free(s);
    free(linenumbers);
    return NULL;
  }
  memcpy(s, string, length);  // Only copy the first 'length' characters.
  s[length] = 0;
  newword->string = s;
  newword->linenumbers = linenumbers;
  newword->linenumbers->number = linenumber;
  newword->linenumbers->next = NULL;
  newword->left = NULL;
  newword->right = NULL;
  return newword;
}

Why is “while ( !feof (file) )” always wrong?

feof(fp) improperly used here. fgetc() returns 257 different values. Do not use char ch.

//char ch;
//...
//while (!feof(fp)) {
//    ch = fgetc(fp);

int ch;
...
while ((ch = fgetc(fp)) != EOF) {;
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • In other words, you still have to initialize, just as you always do in C. There are a few exceptions like some local variables, but generally speaking, get into the habit of always initializing your variables. – Robert Harvey Feb 28 '22 at 15:53
  • @RobertHarvey Always initializing is reasonable axiom for learners. Yet on deeper review, it looks like OP is not accounting for space for a _null character_. – chux - Reinstate Monica Feb 28 '22 at 15:58
0

This is quite normal behaviour. 'malloc' just does the memory allocation, it makes no commitment on what's already in that memory location. What you probably need is 'calloc', which clears the memory and then allocates it to your program.