Home > other >  Test case failing at specific line. Manually works fine - C (needle in haystack)
Test case failing at specific line. Manually works fine - C (needle in haystack)

Time:01-27

I have a C program that takes arguments from the command line. Prints the arguments in reverse order. And finds the needle/substring in the haystack. I have the following code:

Dumb.c

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

#include "Dumb.h"

int main(int argc, char **argv)
{
    int i, j, flag = 0;
    for (i = 1; i < argc; i  )
    {
        char needle[] = "dumb";
        int length = strlen(argv[i]);

        for (j = length - 1; j >= 0; j--)
        {
            printf("%c", argv[i][j]);
            argv[i][j] = tolower(argv[i][j]);
        }

        char *pch = strstr(argv[i], echo);
        if(pch)
        {
            flag = 1;
        }
    }

    if (flag == 1)
    {
        printf("Dumb was found!\n");
    }

    return 0;
}

It works perfectly when I try to run it manually from command line using: ./a.out Dumb.

But when I try to use a special test case for it, it just crashes at this line: argv[i][j] = tolower(argv[i][j]);

Here is the code for the testing:

TestLauncher.c

int unit_test(int argc, char **argv);

int main(int argc, char **argv)
{
    unit_test(argc, argv);
    return 0;
}

Test.c

int __hide_main__(int argc, char **argv);

int unit_test(void)
{
    int retval;
    char **array;
    array = malloc(sizeof(char *) * 2);
    array[0] = "./a.out";
    array[1] = "Dumb";

    retval = __hide_main__(2, array);

    free(array);
    return retval;
}

CodePudding user response:

When you use the string literal "Dumb", it is read-only, unlike the command-line arguments. To see this, try running the following and you should get the same error:

char *arr = "Dumb";
arr[0] = 'd';

To fix this, you should copy the value of argv into a new array rather than modifying it in-place.

CodePudding user response:

But when I try to use a special test case for it, it just crashes at this line: argv[i][j] = tolower(argv[i][j]);

Your program is having undefined behavior as you are trying to modify the string literal. When a program is having undefined behavior, anything can happen like it may work as expected, it may crash etc.

Change this:

array[1] = "Dumb";

to this:

array[1] = strdup("Dumb");

It works perfectly when I try to run it manually from command line using: ./a.out Dumb.

From C Standards (5.1.2.2.1p2):

The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.

So, it is perfectly fine to modify the argument vector which contains the list of the arguments passed (including program name) when running from command line.

Hence the program is working fine when running from command line.

Also, in your program unit_test function declared as:

int unit_test(int argc, char **argv);

but in the definition the signature is not matching:

int unit_test(void)

The compiler must be giving conflicting types error for this or I believe its a typo while you have edited your program before posting.


Follow the good programming practice, always check the malloc return:

array = malloc(sizeof(char *) * 2);
if (NULL == array) {
    fprintf (stderr, "Failed to allocate memory");
    exit(EXIT_FAILURE);
}
  • Related