Thread: Need help to understand unexpected behaviour in user function

  1. #1
    Registered User
    Join Date
    Jul 2020
    Posts
    47

    Need help to understand unexpected behaviour in user function

    Hello,

    I have the following function, which is based on an earlier example (which works) where the code was executed in main.

    So now I'm trying to execute the same logic, but with the code in a function.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void extract_subnet(char ip_address[16],char *ip_subnet[12]);
    
    int main()
    {
        char source_ip_address[16];
        char source_ip_subnet[12];
    
        strcpy(source_ip_address,"192.168.200.150");
        strcpy(source_ip_subnet,"");
    
        extract_subnet(source_ip_address,&source_ip_subnet);
    
        printf("Source IP Address: %s\n",source_ip_address);
        printf("Source IP Subnet: %s\n",source_ip_subnet);
    
        return 0;
    }
    
    
    void extract_subnet(char ip_address[16],char *ip_subnet[12])
    {
        printf("Input IP address: %s\n",ip_address);
    
        int i;
        int period_count = 0;
        char ch;
        int length = strlen(ip_address);
        for(i=0;i<length;i++)
        {
            ch = (ip_address[i]);
    
            if (ch == '.')
            {
                period_count = period_count + 1;
            }
    
            if (period_count == 2)
            {
                break;
            }
    
            ip_subnet[i] = ip_address[i];
         }
         ip_subnet[i] = '\0';
    
         return;
    
    } // extract_subnet
    The issue that I'm observing, is that in the extract_subnet function; when the counter i = 3 and ch should equal the first period ('.') in the IP address (i.e. 192. )

    I can see instead via the debugger that the value in ch is 0

    I don't understand why this is happening.

    I have confirmed via this statement
    Code:
    printf("Input IP address: %s\n",ip_address);
    That the ip_address is being passed correctly to the function.

    Thanks in advance

    VW

  2. #2
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    869
    Start here and note the changes I have made:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    //void extract_subnet(char ip_address[16], char *ip_subnet[12]);
    void extract_subnet(char ip_address[16], char ip_subnet[12]);
    
    int main()
    {
       // Initialize all local variables!
        char source_ip_address[16] = "192.168.200.150";
        char source_ip_subnet[12] = "";
    
    //    No longer needed
    //    strcpy(source_ip_address,"192.168.200.150");
    //    strcpy(source_ip_subnet,"");
    
        extract_subnet(source_ip_address, source_ip_subnet);
    
        printf("Source IP Address: %s\n", source_ip_address);
        printf("Source IP Subnet: %s\n", source_ip_subnet);
    
        return 0;
    }
    
    
    //void extract_subnet(char ip_address[16], char *ip_subnet[12])
    void extract_subnet(char ip_address[16], char ip_subnet[12])
    {
        printf("Input IP address: %s\n", ip_address);
    
        int i;
        int period_count = 0;
        char ch;
        int length = strlen(ip_address);
        for(i=0;i<length;i++)
        {
            ch = (ip_address[i]);
    
            if (ch == '.')
            {
                period_count = period_count + 1;
            }
    
            if (period_count == 2)
            {
                break;
            }
    
            ip_subnet[i] = ip_address[i];
         }
         ip_subnet[i] = '\0';
    
         return;
    
    } // extract_subnet

  3. #3
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Hello rstanley,

    Thanks for responding.

    I'm hoping that you might be able to help me understand how the variable
    Code:
    source_ip_subnet
    is updated in the main function.

    extract_subnet is a void function, so it doesn't return a value.

    And
    Code:
    source_ip_subnet
    is not a global variable.

    So why/how is
    Code:
    source_ip_subnet
    being updated by extract_subnet?

    I have recently seen an example where if you pass a pointer as a function argument (in the example the technique was described as "call by reference"); then the variable in the calling function is updated.

    This is why I made
    Code:
    ip_subnet
    a pointer; because I was trying to use this "call by reference" approach to update the value in
    Code:
    source_ip_subnet
    .

    But in your updated code, the
    Code:
    source_ip_subnet
    is being updated.

    Moreover, if I change
    Code:
    ip_subnet
    back to being a pointer (as per the "call be reference" example) then that is what is producing the unexpected behaviour in the extract_subnet function.

  4. #4
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Here is the "call be reference" example that I was using as a guide for my initial attempt
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void Increment(int *p);
    
    int main()
    {
        int a;
        a = 10;
        Increment(&a);
        printf("a = %d\n",a);
    
        return 0;
    }
    
    
    void Increment(int *p)
    {
        *p = *p + 1;
    }
    And if I change the above code so that I'm not using a pointer as the argument to Increment. Then the code doesn't produce the correct result

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void Increment(int p);
    
    int main()
    {
        int a;
        a = 10;
        Increment(a);
        printf("a = %d\n",a);
    
        return 0;
    }
    
    void Increment(int p)
    {
        p = p + 1;
    }

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,360
    You have to recognise that in this function:
    Code:
    void foo(char s[10]) {}
    The parameter named s is a pointer, not an array. The 10 indicates that the pointer is expected to point to the first char in an array of 10 char, but this is not enforced, and s remains of type char* not char[10].
    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
    Jul 2020
    Posts
    47
    Quote Originally Posted by laserlight View Post
    You have to recognise that in this function:
    Code:
    void foo(char s[10]) {}
    The parameter named s is a pointer, not an array. The 10 indicates that the pointer is expected to point to the first char in an array of 10 char, but this is not enforced, and s remains of type char* not char[10].
    Hello laserlight,

    That is actually quite subtle.

    I have a feeling it is going to be a while before I'm across all these little, but important, details.

    Thanks for the explanation.

  7. #7
    Registered User
    Join Date
    Jul 2020
    Posts
    47
    Hello,

    Unfortunately I'm experiencing issues trying to use this function in my actual code.

    If I run in the debugger I observe
    Code:
    [Inferior 1 (process 43548) exited normally]
    Sometimes when the function is called, so the error is intermittent, but essentially the function is not stable.

    I've tested the standalone function (above) and it works reliably.

    I think the issue is likely due to the fact that the input to the function in the actual code is like this

    Code:
    strcpy(source_ip_address,inet_ntoa(source.sin_addr));
    I've checked the contents of source_ip_address via the debugger and it looks normal.

    I can also printf inet_ntoa(source.sin_addr) without issue.

    But I've noticed in some cases when I enter the extract_subnet function, that when I get to this line
    Code:
    int length = strlen(ip_address);
    length evaluates to 0. Which is clearly wrong, but that makes me think that somehow despite on the surface the value in source_ip_address looks OK. Somehow deep down something is wrong.

    Am hoping for some troubleshooting suggestions.

    Thanks

    VW

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,360
    You could have a buffer overflow elsewhere that is corrupting memory, and so it looks like the problem is with this function when it is actually elsewhere.
    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. Unexpected behaviour of a simple C program
    By Lucky Luka in forum C Programming
    Replies: 4
    Last Post: 02-24-2019, 06:53 AM
  2. Unexpected behaviour of pthread_cond_broadcast
    By Imago in forum C Programming
    Replies: 1
    Last Post: 01-17-2019, 12:10 PM
  3. Unexpected variable behaviour
    By Dondrei in forum C++ Programming
    Replies: 5
    Last Post: 02-24-2009, 12:11 AM
  4. Unexpected behaviour with float
    By j.sreejit in forum C Programming
    Replies: 6
    Last Post: 09-14-2006, 09:53 PM
  5. Unexpected behaviour
    By fnoyan in forum C++ Programming
    Replies: 5
    Last Post: 03-05-2005, 09:45 AM

Tags for this Thread