Thread: Strncpy not working properly in windows?...

  1. #1
    Registered User
    Join Date
    Sep 2009
    Posts
    8

    Strncpy not working properly in windows?...

    So, I have to write a program that among other things, parses a string and breaks it up.

    So if I have the input "ps -aux" I need to store this in an output array where output[0] = "ps", output[1] = "-aux" and output[2] = NULL.

    The program is supposed to run smoothly on Linux, which it does...but, for some reason doesn't run properly at all on windows. This wouldn't be much of an issue, except for the fact that I'm only using standard library functions to achieve this goal at the moment, so I fear something may be wonky in my code and I"m just not picking up on it...

    The way I've approached it is like thus:

    a) read in a string
    b) break it up into the 'parameters/program name'
    c) (testing) print out the program name

    Part (b) is accomplished by first stripping off any leading or trailing whitespace that could possibly be input. Then we find the first string, using ' ' as a delimiter. Continue this process until we've exhausted the original input and have now broken it up into several different strings.

    What's the problem exactly? Well, windows keeps printing "ps4" or something similarly wacky (like -aux4...junk chars...) when I try to print any other things in the array (well, double pointer, but I'm using array syntax to index it). Linux does JUST fine and everything is nice and good.

    But why the hell is windows randomly adding a new character(s) to my strings? I can't ANYWHERE find where it's getting these extra chars. I'll check the string before I call strncpy() and it seems all fine and what have you, but then I call the function and suddenly the string is not only longer than what I wanted it to be, but it also has extra chars! Is this a programming error on my behalf, or is it windows just being windows?

    Here is the main function:

    Code:
    	char *ptr = "    ps -aux ";
    	char **test = getparams(ptr);
    	
    	printf("%s", test[0]);
    The getparams(const char *input) function:

    Code:
    	char **output;
    	int i;
    	char *tmp = (char *)input;
    	size_t counter = 1;
    	
    	tmp = strtrim(tmp);
    	output = malloc(strlen(tmp)*sizeof(char *)); // num(params+prgname) <= strlen(input)
    	output[0] = strfind(tmp, ' ');
    
    	for(i = strlen(output[0]); tmp[i] != '\0'; )
    	{
    		if(!isspace(tmp[i])) 
    		{
    			output[counter] = strfind(tmp+i, ' '); 
    			i += strlen(output[counter]);
    			counter++;
    		}
    		else
    		{
    			i++;
    		}
    	}
    	
    	output = realloc(output, (counter+1) * sizeof(char *));
    	output[counter] = NULL;
    	
    	return output;
    And the two utility functions strfind and strtrim...

    strfind(const char *src, char c):

    Code:
    	char cur = *src;
    	char *dst, *tmp = (char *)src;
    	size_t size;
    
    	for(size = 1; tmp[size] != '\0' && tmp[size] != c; size++) cur = tmp[size];
    
    	dst = malloc(size+1);
    	strncpy(dst, src, size);	
    
    	return dst;
    strtrim(const char *src):

    Code:
    	int i = 0; 
    	size_t diff = 0, len = strlen(src);
    	char *start, *s;
    
    	// count leading whitespace
    	while(isspace(src[i])) 
    	{
    		i++;
    		diff++;
    	}
    
    	start = src+i; // the bit we're interested in starts at src+i
    
    	i = len-1; // back end starts at src[len-1]
    
    	// count trailing whitespace
    	while(isspace(src[i])) 
    	{
    		i--;
    		diff++;
    	}
    
    	s = malloc(len-diff+1); // bytes required = old length - whitespace chars + '\0'
    
    	strncpy(s, start, len-diff); // copy nonwhitespace chars into a new string
    
    	return s;

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Perhaps I've gotten lost, but your for loop -- why do you start i at strlen(output[0])?

  3. #3
    Registered User
    Join Date
    Sep 2009
    Posts
    8
    Quote Originally Posted by tabstop View Post
    Perhaps I've gotten lost, but your for loop -- why do you start i at strlen(output[0])?
    Lol, never mind that, it was written earlier. I've actually changed the code, it starts at 0 now, less confusing. But the point of starnig at strlen(output[0]) is to skip strlen(output[0]) characters to start analyzing the next set of chars.

    Windoze still giving random results...it seems every time I fix it in windows, it buggers up in Linux. So then I fix the issue in linux, and windows starts acting up..

  4. #4
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    Quote Originally Posted by alman9898 View Post
    So if I have the input "ps -aux" I need to store this in an output array where output[0] = "ps", output[1] = "-aux" and output[2] = NULL.
    As an aside, are you aware that although ps on your Linux machine will accept both BSD and System V options? Thus, ps -aux (System V style) is not the same as ps aux (BSD style). You may luck out and it will work ok, but it may not either. If you want to print all the running processes with System V style options, try something like ps -eF. You can read about all of this and more in the ps man page.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Well, but in your example given, output[0] would appear to be "ps -aux ", so strlen of that is 8, and you don't want to skip eight things.

    Anyway, I would suggest using a debugger to step through your code and see where you're off by one (that's what seems likely).

  6. #6
    Registered User
    Join Date
    Sep 2009
    Posts
    8
    Quote Originally Posted by tabstop View Post
    Well, but in your example given, output[0] would appear to be "ps -aux ", so strlen of that is 8, and you don't want to skip eight things.

    Anyway, I would suggest using a debugger to step through your code and see where you're off by one (that's what seems likely).
    No, output[0] will be "ps" at least. White space is stripped first, then strfind is SUPPOSED to return everything up to but not including the delimiter ' ', which means it should only have "ps" left...like I said, works well in linux, but windows is giving weird results. I agree that it's something off by one, but I don't know exactly what...and the fact that it keeps using the character '4' is also puzzling. To be a bit clearer, it'll return something like 'ps4' as the string in test[0].

    As an aside, are you aware that although ps on your Linux machine will accept both BSD and System V options? Thus, ps -aux (System V style) is not the same as ps aux (BSD style). You may luck out and it will work ok, but it may not either. If you want to print all the running processes with System V style options, try something like ps -eF. You can read about all of this and more in the ps man page.
    Well, I'm a Linux newbie so no I didn't although I did get messages about ps -aux being "bad form." It 's not really a concern, I just need to be able to break up a command into its program name and parameters so I can eventually feed them to an exec call. The fact that strfind works and doesn't work troubles me because I need it for both this parsing bit, and the other part of my project (which is implementing pipelining but that's not a question I've got for you guys )

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I stepped through it in the debugger. You malloc a bunch of memory in strtrim, but never bother putting the \0 character at the end. Easy fix: change that malloc to calloc.

  8. #8
    Registered User
    Join Date
    Sep 2009
    Posts
    8
    Quote Originally Posted by tabstop View Post
    I stepped through it in the debugger. You malloc a bunch of memory in strtrim, but never bother putting the \0 character at the end. Easy fix: change that malloc to calloc.
    Hmmm, I guess I assumed strncpy would put the '\0' in there for me. I'll give it a go.

    UPDATE: !!!

    I found a similar problem in strfind and changed it to calloc and everything output fine! Now to see if Linux likes my new code

    Thanks a lot, dude!
    Last edited by alman9898; 09-27-2009 at 07:38 PM.

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Strncpy will only copy as many characters as you say -- if you want \0, you have to either count it in your "n" or do it later.

  10. #10
    Registered User
    Join Date
    Sep 2009
    Posts
    8
    Quote Originally Posted by tabstop View Post
    Strncpy will only copy as many characters as you say -- if you want \0, you have to either count it in your "n" or do it later.
    Yea, I know that now. Still strange that it would work in Linux, but not windows.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Undefined behavior it is called.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Parallel Port IO ops not working properly
    By microtechno in forum Linux Programming
    Replies: 16
    Last Post: 06-08-2009, 12:33 PM
  2. Replies: 9
    Last Post: 03-30-2009, 04:09 AM
  3. gcc compiler not working in windows vista
    By taurus in forum C Programming
    Replies: 1
    Last Post: 03-05-2009, 01:11 AM
  4. tic tac toe not working properly
    By h_howee in forum Game Programming
    Replies: 2
    Last Post: 01-01-2006, 01:59 AM
  5. GetDiskFreeSpaceEx not working on windows XP
    By OOPboredom in forum C++ Programming
    Replies: 1
    Last Post: 05-14-2004, 10:58 PM