Thread: Null pointer handling Linux vs Windows

  1. #1
    Just kidding.... fnoyan's Avatar
    Join Date
    Jun 2003
    Location
    Still in the egg
    Posts
    275

    Null pointer handling Linux vs Windows

    Hi

    I have a function that checks the value pointed by a string literal. In case of NULL pointer, function supposed to return NULL as return value.

    When I compiled code in linux, I could not catch the NULL pointer with "static_str == 0" test condition but I had to write "static_str[0] == 0" which seems weird.

    In Windows (Win 7, Mingw), the "static_str[0] == 0" did not work but "static_str == 0".

    Is there a difference in handling of NULL pointer between OS's? Actually, the code I use in Win does more sense to me.

    Below is a code snippet from the function
    Code:
    char *foo(char *str, const char *delim) {
    	static char *static_str=0;		/* var to store last address */
    
    	/* delimiter cannot be NULL
    	* if no more char left, return NULL as well
    	*/
    	if (delim==0 || (str == 0 && static_str == 0))
    		return 0;

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by fnoyan View Post
    When I compiled code in linux, I could not catch the NULL pointer with "static_str == 0" test condition but I had to write "static_str[0] == 0" which seems weird.
    How did you draw the conclusion that you needed to do that? Because it is outright wrong.

    Your code initialises static_str to a NULL pointer. Dereferencing a NULL pointer (for example, accessing the value of static_str[0], when static_str is NULL) yields undefined behaviour. Anything is allowed to happen (a program crash, reformatting your hard drive) at that point.

    My guess is that you left out an asterix in the linux version of the code (for example, "static char static_str = 0" rather than "static char *static_str = 0"). A compiler is not at fault when programmers make errors, and compile the wrong code.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Just kidding.... fnoyan's Avatar
    Join Date
    Jun 2003
    Location
    Still in the egg
    Posts
    275
    Actually, I just copied the header file to my Win disk and compile the code again. No compiler error in Windows but program crashed. I opened the program in GDB and examined the function and realized that the program crashes at that point. Although, static_str[0] also does not makes sense to me, I cannot evaluate the cases where both str and static_str is set to NULL.

    Please note, this is a strtok() like function that, after first call, static_str has the value retained from last call of the function foo().

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Can you post the whole function, and a simple main() you use to test it.
    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.

  5. #5
    Just kidding.... fnoyan's Avatar
    Join Date
    Jun 2003
    Location
    Still in the egg
    Posts
    275
    Code:
    #include <stdio.h>
    
    char *zStrtok(char *str, const char *delim) {
    	static char *static_str=0;		/* var to store last address */
    	int index=0, strlength=0;		/* integers for indexes	*/
    	int found = 0;				/* check if delim is found */
    
    	/* delimiter cannot be NULL
    	* if no more char left, return NULL as well
    	*/
    	if (delim==0 || (str == 0 && static_str == 0))
    		return 0;
    
    	if (str == 0)
    		str = static_str;
    
            /* get length of string */
            while(str[strlength])
                    strlength++;
    
    	/* find the first occurance of delim */
    	for (index=0;index<strlength;index++)
    		if (str[index]==delim[0]) {
    			found=1;
    			break;
    		}
    
    	/* if delim is not contained in str, return str */
    	if (!found) {
    		static_str = 0;
    		return str;
    	}
    
    	/* check for consecutive delimiters
    	*if first char is delim, return delim
    	*/
    	if (str[0]==delim[0]) {
    		static_str = (str + 1);
    		return (char *)delim;
    	}
    
    	/* terminate the string
    	* this assignmetn requires char[], so str has to
    	* be char[] rather than *char which will cause SIGSEGV
    	*/
    	str[index] = '\0';
    
    	/* save the rest of string */
    	if ((str + index + 1)!=0)
    		static_str = (str + index + 1);
    	else
    		static_str = 0;
    
    		return str;
    }
    
    int main() {
    char s[]="A,B,C,D,E,F,G,H,I";
    printf("1  %s\n",zStrtok(s,","));
    printf("2  %s\n",zStrtok(NULL,","));
    printf("3  %s\n",zStrtok(NULL,","));
    printf("4  %s\n",zStrtok(NULL,","));
    printf("5  %s\n",zStrtok(NULL,","));
    printf("6  %s\n",zStrtok(NULL,","));
    printf("7  %s\n",zStrtok(NULL,","));
    printf("8  %s\n",zStrtok(NULL,","));
    printf("9  %s\n",zStrtok(NULL,","));
    printf("10  %s\n",zStrtok(NULL,","));
    printf("11  %s\n",zStrtok(NULL,","));
    printf("12  %s\n",zStrtok(NULL,","));
    printf("13  %s\n",zStrtok(NULL,","));
    printf("14  %s\n",zStrtok(NULL,","));
    return 0;
    }
    after 10th printf(), it is (null), if static_str[0] is used, program crashes in Win whereas, in linux, I had to add it to evaluate the case.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Well it seems to work "as is" in Linux.

    > * this assignmetn requires char[], so str has to
    > * be char[] rather than *char which will cause SIGSEGV
    Writing *(str+index) = '\0'; would be the same thing.
    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.

  7. #7
    Just kidding.... fnoyan's Avatar
    Join Date
    Jun 2003
    Location
    Still in the egg
    Posts
    275
    technically, they are the same, aren't they? I used the first convention for ease of code review.
    Code:
    str[index] = '\0'; != *(str+index) = '\0';
    But what is the effect of this to the line 11 where the code crashes

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    If static_str is NULL, then static_str[0] will segfault.

    If you want to test for pointing to the \0 at the end of a string, it would be
    static_str != NULL && static_str[0] == '\0'
    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.

  9. #9
    Just kidding.... fnoyan's Avatar
    Join Date
    Jun 2003
    Location
    Still in the egg
    Posts
    275
    Well, I will definitely try to snippet you gave. But before that, won't it give SIGSEGV before evaluating the condition in the code static_str != NULL && static_str[0] == '\0'?

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > static_str != NULL && static_str[0] == '\0'?
    Well if static_str is NULL, then though short-circuit evaluation of &&, the right hand side will not be evaluated at all.
    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.

  11. #11
    Just kidding.... fnoyan's Avatar
    Join Date
    Jun 2003
    Location
    Still in the egg
    Posts
    275
    Hmm....Ok, coming back to first question. Why it run in Linux fine but crashed under Win? There is simply a bug in the code, but why Linux did not crash ( well, this can't be because it is more robust OS than redmond OS :} )

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    I can't see anything wrong with the code in post #5

    Nor does valgrind spot any illegal memory accesses.
    Code:
    $ valgrind ./a.out
    ==2695== Memcheck, a memory error detector
    ==2695== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
    ==2695== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
    ==2695== Command: ./a.out
    ==2695== 
    1  A
    2  B
    3  C
    4  D
    5  E
    6  F
    7  G
    8  H
    9  I
    10  (null)
    11  (null)
    12  (null)
    13  (null)
    14  (null)
    ==2695== 
    ==2695== HEAP SUMMARY:
    ==2695==     in use at exit: 0 bytes in 0 blocks
    ==2695==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
    ==2695== 
    ==2695== All heap blocks were freed -- no leaks are possible
    ==2695== 
    ==2695== For counts of detected and suppressed errors, rerun with: -v
    ==2695== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
    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.

  13. #13
    Just kidding.... fnoyan's Avatar
    Join Date
    Jun 2003
    Location
    Still in the egg
    Posts
    275
    Actually, I meant static_str[0] version (in line 11 at post #5)

  14. #14
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by fnoyan View Post
    Why it run in Linux fine but crashed under Win? There is simply a bug in the code, but why Linux did not crash ( well, this can't be because it is more robust OS than redmond OS :} )
    Undefined behaviour - as the word "undefined" is defined in the C standard - is like that. With one compiler, the code may seem to work. With another, it may crash. Either way, the compiler is not required to diagnose a problem. The symptoms (to crash or not) can even change by tweaking compilation options.

    This really has nothing to do with operating system. Code that enters the realm of undefined behaviour, as your code has done, can do anything. There are also plenty of real-world cases where code with undefined behaviour seems perfectly fine under windows, but breaks when build and executed under unix. (In fact, in practice, that scenario is more common in forums like this one, since a lot of people learn to program under windows, and run into trouble some months later when porting their code to unix).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Does static initialization of pointer make it null pointer
    By Saurabh Mehta in forum C Programming
    Replies: 1
    Last Post: 11-23-2012, 12:05 AM
  2. Null Pointer
    By saswatdash83 in forum C Programming
    Replies: 3
    Last Post: 07-15-2008, 04:12 AM
  3. fread() error handling on Linux
    By cdalten in forum C Programming
    Replies: 9
    Last Post: 03-12-2006, 08:36 PM
  4. what is a null pointer?
    By forest in forum C Programming
    Replies: 6
    Last Post: 11-02-2002, 11:02 AM
  5. pointer always NULL?
    By endo in forum C++ Programming
    Replies: 5
    Last Post: 08-14-2002, 03:10 AM