Thread: Some very strange behaviour with argv

  1. #1
    Registered User
    Join Date
    Mar 2010
    Posts
    3

    Some very strange behaviour with argv

    For some reason, using <string.h> functions on argv[1] messes up the values in my global arrays.

    Here is a shortened version of my code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char* username[50];
    char* password[50];
    char* type[50];
    int recordcount;
    
    /*...
    some functions
    ...*/
    
    int main(int argc, char* argv[])
    {
    	getData(); //Reads some file and stores stuff into the 3 global string arrays
    
    	if (argc == 1)
    		syntaxerror(); //Checks there is at least one extra parameter when calling the program
    
    	if (strcmp("-menu",argv[1]) == 0) //Calls menu() if the 1st parameter is -menu
    		menu();
    	else
    	{
    		/* Rest of program */
    So for example when I tested the program, username[0] is what it's supposed to be until it hits the line:
    if (strcmp("-menu", argv[1]) == 0).
    Then, username[0] changes its value completely.
    menu() was never called when testing.

    I tested it even further and when just doing a strcmp("menu", argv[1]); by itself, it did not change username[0]. However, it did when putting it in an if statement and comparing it to 0.

    I cannot think of any reason why it would do this...

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The problem probably lies in getData() or a function that it calls.

    By the way, why are those arrays global?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Here is a shortened version of my code:
    You need to post everything that gets run up to the point that you notice the problem.

    If cause and effect were in the same place, you would have fixed it yourself.

    But since the cause is further away, you just post the effect because that is the bit which makes no sense.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Mar 2010
    Posts
    3
    They are global because many of the functions need to access them, and it's more convenient than passing them as parameters.

    Alright here's the program (modified for testing) everything that runs up to the point of where it messes up

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char* username[50];
    char* password[50];
    char* type[50];
    int recordcount;
    
    //Gets all the data for the 3 arrays containing usernames, passwords, and types
    
    int getData()
    {
    	FILE* pfile;
    	pfile = fopen("password.csv", "a+");
    
    	char * token;
    	char line[300];
    	int i = 0;
    
    	while (fgets(line, 300, pfile) != NULL)
    	{
    		printf("Getting the line: %s", line);
    		token = strtok(line,",");
    		printf("Token 1 stored in username[%d]: %s\n", i, token);
    		username[i] = token;
    		token = strtok(NULL,",");
    		printf("Token 2 stored in password[%d]: %s\n", i, token);
    		password[i] = token;
    		token = strtok(NULL,"\n");
    		printf("Token 3 stored in type[%d]: %s\n", i, token);
    		type[i] = token;
    		i++;	
    	}
    	recordcount = i;
    	return 0;
    }
    
    int main(int argc, char* argv[])
    {	
    	getData();
    
    	//Checks that there aren't no parameters
    	if (argc == 1)
    		syntaxerror();
    
    	printf("Test 0: %s, %s, %s\n", username[0], password[0], type[0]);
    
    	char * switchParameter = argv[1];
    	printf("Test 1: %s, %s, %s\n", username[0], password[0], type[0]);
    
    	if (strcmp("-menu",switchParameter) == 0)
    		menu();
    	else
    	{
    		printf("Test 2: %s, %s, %s\n", username[0], password[0], type[0]);
    
    		/*Rest of program*/
    	}
    }
    This is tested using a password.csv file with just the single line:
    Code:
    abc,def,ghi
    running ./a.out [somerandomparameter not -menu]
    and the output up to this point is:
    Code:
    Getting line: abc,def,ghi
    Token 1 stored in username[0]: abc
    Token 2 stored in password[0]: def
    Token 3 stored in type[0]: ghi
    Test 0: abc, def, ghi
    Test 1: abc, def, ghi
    Test 2: �W�, , 8��
    Now as you can see... Test 2 is completely messed up and I have no idea why.
    Thanks in advance guys, really appreciate it.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by dnl
    They are global because many of the functions need to access them, and it's more convenient than passing them as parameters.
    I am wary of using convenience as an excuse as global variables can be terribly inconvenient when it comes to understanding and maintaining a program, or integrating a program into a larger work. Personally, I would define a struct, say, User, which has a username, password and type. Then passing around a pointer to the first element of this single array of User objects with the recordcount is not too inconvenient. (Wait, you can even combine this array and the recordcount into another struct!)

    Quote Originally Posted by dnl
    Alright here's the program (modified for testing) everything that runs up to the point of where it messes up
    This looks problematic:
    Code:
    username[i] = token;
    The problem is that line is local to getData(). After the function returns, line no longer exists, and so username[i] points to something that no longer exists. In fact, since line gets overwritten on each iteration, using the result of strtok() like this is problematic even if you made line global.

    You need to allocate memory for username[i] with say, malloc() or changing it to an array, then copy over the string. If you use malloc(), you should remember to free() at an appropriate time.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Mar 2010
    Posts
    3
    ahhh yes I see now, thanks!
    To fix it, I just replaced the things with username[i] = strdup(token);

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by dnl
    To fix it, I just replaced the things with username[i] = strdup(token);
    Note that strdup is non-standard with respect to the C standard, and using it does not absolve you from the need to use free() at the appropriate time.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Strange behaviour of printf
    By pshirishreddy in forum C Programming
    Replies: 5
    Last Post: 08-29-2009, 11:46 PM
  2. strange scanf behaviour
    By cavva in forum C Programming
    Replies: 3
    Last Post: 08-10-2009, 12:44 PM
  3. Strange behaviour of GCC
    By BlackOps in forum C Programming
    Replies: 14
    Last Post: 07-29-2009, 06:44 PM
  4. GetClientRect strange behaviour
    By btq in forum Windows Programming
    Replies: 2
    Last Post: 10-02-2002, 02:13 PM
  5. Strange behaviour
    By PrivatePanic in forum Windows Programming
    Replies: 11
    Last Post: 07-23-2002, 12:54 AM