Elemental
Elemental

Reputation: 39

Valgrind - uninitialized value

The following code is part of a larger program, so I created a test file to try to isolate the problem. The code is working fully as intended, but it is throwing a valgrind error. From my understanding, I think it is most likely referring to *inputStr.

Valgrind error message:

==2807== Conditional jump or move depends on uninitialised value(s)
==2807==    at 0x3156434819: ____strtol_l_internal (in /lib64/libc-2.5.so)
==2807==    by 0x3156431BD1: atoi (in /lib64/libc-2.5.so)
==2807==    by 0x400818: getInt (test.c:50)
==2807==    by 0x4008B5: main (test.c:70)
==2807==  Uninitialised value was created by a stack allocation
==2807==    at 0x400668: getInt (test.c:13)
==2807== 
==2807== Conditional jump or move depends on uninitialised value(s)
==2807==    at 0x315643482F: ____strtol_l_internal (in /lib64/libc-2.5.so)
==2807==    by 0x3156431BD1: atoi (in /lib64/libc-2.5.so)
==2807==    by 0x400818: getInt (test.c:50)
==2807==    by 0x4008B5: main (test.c:70)
==2807==  Uninitialised value was created by a stack allocation
==2807==    at 0x400668: getInt (test.c:13)
==2807== 
==2807== Use of uninitialised value of size 8
==2807==    at 0x31564348A8: ____strtol_l_internal (in /lib64/libc-2.5.so)
==2807==    by 0x3156431BD1: atoi (in /lib64/libc-2.5.so)
==2807==    by 0x400818: getInt (test.c:50)
==2807==    by 0x4008B5: main (test.c:70)
==2807==  Uninitialised value was created by a stack allocation
==2807==    at 0x400668: getInt (test.c:13)

My code: Parses input command via stdin (e.g. "i 5"), the "i" would be used in a menu switch (but that code is removed), then calls getInt(), which starts scanning the inputStr at index 1 to parse the integer value from the inputStr. I have marked error lines 13, 50, and 70 as comments for clarity.

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

int getInt(char *inputStr, int *value, int *i) { // <-----line 13
    char num[5];
    int ctr = 0;

    /* Skip whitespace */
    while (!isdigit(*(inputStr+(*i))) && *(inputStr+(*i)) != '-') {
        /* Input with only command letter and no integer value */
        if (*(inputStr+(*i)) == '\n') {
            //printError(-1);
            return -1;
        }
        /* Input has invalid characters after command letter */
        if (!isspace(*(inputStr+(*i)))) {
            //printError(-2);
            return -2;
        }
        (*i)++;
    }

    if (*(inputStr+(*i)) == '-') {
        num[ctr++] = *(inputStr+(*i));
        (*i)++;
    }

    /* Copy number characters to another array */
    while (isdigit(*(inputStr+(*i)))) {
        num[ctr++] = *(inputStr+(*i));
        (*i)++;
    }

    /* Check if unwanted characters terminated the while loop above */
    if (!isspace(*(inputStr+(*i)))) {
        //printError(-2);
        return -2;
    }

    /* Convert number characters to integer */
    *value = atoi(num);                              // <----line 50

    //printf("Positive Integer: num = %s, value = %d\n",num, value);
    return 0;
}


int main () {
    int value, i, int1;
    char *inputStr;
    size_t sizeInput = 10;
    inputStr = malloc(sizeof(char) * sizeInput);

    for (i = 0; i < sizeInput; i++)
        inputStr[i] = '\0';

    value = 0;
    i = 1; //starting position for parsing number

    getline(&inputStr, &sizeInput, stdin);
    int1 = getInt(inputStr, &value, &i);  // <---line 70
    printf ("%d\n", value);

    free(inputStr);
    return 0;
}

Appreciate the help.

[Resolved] thanks to @JonathanLeffler. Added num[ctr] = '\0'; one line above the atoi() conversion. Now error free.

Upvotes: 3

Views: 5272

Answers (1)

Matt
Matt

Reputation: 6050

You have multiple errors:

  1. getline return new memory by first parameter if the buffer is not large enough to hold the line, so you don't need allocate memory for inputStr, but you have to free it. You can just set inputStr to NULL, the getline will return new memory.

  2. when you call function getInt, variable 'i' is initialize as 1; C/C++ array index starts with 0, so it should be 0, I don't know if you intend to pass 1 as the first.

  3. in function getInt, the variable 'num' is not initialized if the while and if block are not excectuted, you can change it to:

    char num[5] = {0};

  4. Also in function getInt, no code to check if the string inputStr is already ended, so your loops may cause access violation.

Upvotes: 1

Related Questions