Thread: enum value changes when passing into function

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    74

    enum value changes when passing into function

    Hi,

    I am experiencing a strange behavior when using enum.

    My enum is as follows:

    Code:
    typedef enum {
        L_R = 0,
        L_I,
        L_L,
    }S_LEVEL;
    Next, I have a structure, and I am using this enum as type for one member of this structure:

    Code:
    typedef struct SV {
        int s_id;
        int s_p;
        int s_b;
        S_LEVEL s_lvl;  
        int s_u;	
        int s_d;	
    }sv_t, *s_ptr;
    Next step is when I fill the structure SV.

    Code:
    void a_function() {
     
           sv_t sv;
           s_ptr svp;
     
    
            sv.s_id = 45;
            sv.s_p = 35;
            sv.s_b = 400;
            sv.s_lvl = L_L;     // this must be 2
            sv.s_u = 2;
            sv.s_d = 3;
                    
            /*************************************/
            /*  FIRST PRINT                         */
            /*************************************/
            printf(" server %d level is %s \n", sv.s_id, (sv.s_lvl == L_L ? "level is L" : ((sv.s_lvl == L_I) ? "level is I" : "level is R"));
    
            svp = &sv;
            b_function(svp)
        
    
    }
    Code:
    void b_function(s_ptr s) {
    
        /*************************************/
        /*  SECOND PRINT                    */
        /*************************************/	
    
        printf(" adding an item .... \n");
        printf(" server %d level is (%d, %s) \n", s->s_id, s->s_lvl, (s->s_lvl == L) ? "level is L" : ((s->s_lvl == I) ? "level is I" : "level is R"));
    }
    Here is what I receive as output:

    // First print
    server 45 level is L_L
    which is correct

    // Second print
    server 45 level is (0, L_R)
    which is wrong

    Why is this value changing ?

    thanks,

    Zahid

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > (s->s_lvl == L)
    Well since L isn't part of your enum, what aren't you telling us?

    > server 45 level is L_L
    But your print only prints L ?

    Anyway, this works.
    Code:
    $ cat foo.c && ./a.out
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    
    typedef enum {
        L_R = 0,
        L_I,
        L_L,
    }S_LEVEL;
    
    typedef struct SV {
        int s_id;
        int s_p;
        int s_b;
        S_LEVEL s_lvl;
        int s_u;
        int s_d;
    }sv_t, *s_ptr;
    
    void b_function(s_ptr s) {
    
        /*************************************/
        /*  SECOND PRINT                    */
        /*************************************/
    
        printf(" adding an item .... \n");
        printf(" server %d level is (%d, %s) \n", s->s_id, s->s_lvl, s->s_lvl == L_L ? "level is L" : s->s_lvl == L_I ? "level is I" : "level is R");
    }
    
    void a_function() {
    
           sv_t sv;
           s_ptr svp;
    
    
            sv.s_id = 45;
            sv.s_p = 35;
            sv.s_b = 400;
            sv.s_lvl = L_L;     // this must be 2
            sv.s_u = 2;
            sv.s_d = 3;
    
            /*************************************/
            /*  FIRST PRINT                         */
            /*************************************/
            printf(" server %d level is %s \n", sv.s_id, sv.s_lvl == L_L ? "level is L" : sv.s_lvl == L_I ? "level is I" : "level is R");
    
            svp = &sv;
            b_function(svp);
    
    
    }
    
    int main(int argc, char** argv) {
      a_function();
      return (EXIT_SUCCESS);
    }
     server 45 level is level is L 
     adding an item .... 
     server 45 level is (2, level is L)
    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.

  3. #3
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    thanks for the reply.

    However, in my program this strange behavior is persisting.
    Until before the call to "b_function()" the values are correct, but inside the "b_function()" whenever I print, I receive the wrong output.

    I am trying to debug this now with gdb.

    thanks,

    zahid


    Quote Originally Posted by Salem View Post
    > (s->s_lvl == L)
    Well since L isn't part of your enum, what aren't you telling us?

    > server 45 level is L_L
    But your print only prints L ?

    Anyway, this works.
    Code:
    $ cat foo.c && ./a.out
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    
    typedef enum {
        L_R = 0,
        L_I,
        L_L,
    }S_LEVEL;
    
    typedef struct SV {
        int s_id;
        int s_p;
        int s_b;
        S_LEVEL s_lvl;
        int s_u;
        int s_d;
    }sv_t, *s_ptr;
    
    void b_function(s_ptr s) {
    
        /*************************************/
        /*  SECOND PRINT                    */
        /*************************************/
    
        printf(" adding an item .... \n");
        printf(" server %d level is (%d, %s) \n", s->s_id, s->s_lvl, s->s_lvl == L_L ? "level is L" : s->s_lvl == L_I ? "level is I" : "level is R");
    }
    
    void a_function() {
    
           sv_t sv;
           s_ptr svp;
    
    
            sv.s_id = 45;
            sv.s_p = 35;
            sv.s_b = 400;
            sv.s_lvl = L_L;     // this must be 2
            sv.s_u = 2;
            sv.s_d = 3;
    
            /*************************************/
            /*  FIRST PRINT                         */
            /*************************************/
            printf(" server %d level is %s \n", sv.s_id, sv.s_lvl == L_L ? "level is L" : sv.s_lvl == L_I ? "level is I" : "level is R");
    
            svp = &sv;
            b_function(svp);
    
    
    }
    
    int main(int argc, char** argv) {
      a_function();
      return (EXIT_SUCCESS);
    }
     server 45 level is level is L 
     adding an item .... 
     server 45 level is (2, level is L)

  4. #4
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    Hi,

    thanks for the reply.

    However, I have been getting the same strange behavior.
    Before "b_function" is called, I can see the correct output (level is L_I) but inside "b_function" its always the same (level is L_R).
    I am trying to debug this with gdb dubugger. But, there is something very strange though: I print out the value of "pointer s_ptr" which is passed to function "b_function". This value does not change outside or inside the function, then, why does the value of one of the members of the structure i.e. s_lvl is different.

    thanks,

    Zahid

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Are you entirely sure that both functions are seeing the same header file?

    One cause of trouble may be having some other structure / pointer overwriting your data.
    debugging - Can I set a breakpoint on &#39;memory access&#39; in GDB? - Stack Overflow

    > sv.s_lvl = L_L; // this must be 2
    Immediately after this, set a watch point on that memory location, then you'll find who changes 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.

  6. #6
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    Quote Originally Posted by Salem View Post
    Are you entirely sure that both functions are seeing the same header file?

    One cause of trouble may be having some other structure / pointer overwriting your data.
    debugging - Can I set a breakpoint on 'memory access' in GDB? - Stack Overflow

    > sv.s_lvl = L_L; // this must be 2
    Immediately after this, set a watch point on that memory location, then you'll find who changes it.
    Hi,

    thanks for your help. I write more about this issue.

    Inside the caller function which is "a_function()", I have two variables of the structure SV. One variable is sv_t sv, and other variable is s_ptr svp.
    Now, I initialize these variables as follows:

    Code:
    server_t sv = {0};
    S_Ptr svp = nullptr;
    next, I fill the structure variables, and assign the address of sv to svp.

    Code:
    	sv.s_id = 45;
            sv.s_p = 35;
            sv.s_b = 400;
            sv.s_lvl = L_L;     
            sv.s_u = 2;
            sv.s_d = 3;
    	
    
    	svp = &sv;


    Finally, I call b_function().

    Code:
     
    
    b_function(svp)
    Here are my gdb outputs. And you can see some values have changed.

    Code:
    (gdb) print sv
    $11 = {s_id = 45, s_p = 35, s_b = 400, s_lvl = L_L, s_u = 2, 
      s_d = 3}
    (gdb) print svp
    $12 = (S_Ptr) 0x0
    (gdb) step
    109	        b_function(svp);
    (gdb) print svp
    $13 = (S_Ptr) 0xbffff32c
    (gdb) print *svp
    $14 = {s_id = 45, s_p = 35, s_b = 400, s_lvl = L_L, s_u = 2, 
      s_d = 3}
    step
    b_function (server=0xbffff32c) at M_sv_db.c:107
    (gdb) print server
    $15 = (S_Ptr) 0xbffff32c
    (gdb) print *server
    $16 = {s_id = 45, s_p = 35, s_b = 400, s_lvl = L_R, s_u = 1, 
      s_d = 3}

    thanks for help.

    zahid

  7. #7
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    Another note:

    However, when I try to watch just the memory location which relates with "sv.s_lvl" i.e. address "0xbffff344",
    this is the output that I receive which I am not able to comprehend.

    Code:
     
    (gdb) watch *0xbffff344
    Hardware watchpoint 2: *0xbffff344
    (gdb) r
    Starting program: /home/.......
    Hardware watchpoint 2: *0xbffff344
    Old value = 0
    New value = -1207963648
    0xb7ff1fd2 in calloc (nmemb=749, size=1) at dl-minimal.c:103
    103	dl-minimal.c: No such file or directory.
    thanks,

    zahid

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well when the breakpoint is hit, you can do 'bt' to find out where your originating line is (in your own code).

    But the fact that malloc/calloc is doing the trashing probably means you've messed up your use of dynamic memory.

    As such, the real problem could be absolutely anywhere in your code.

    Such errors to consider are
    - not allocating enough memory to begin with (buffer overrun)
    - forgetting that realloc can move memory
    - using memory after freeing it
    - trying to free it twice
    - freeing something you didn't malloc

    Valgrind Home
    valgrind runs your code in an encapsulated environment, and can tell you a lot about how you're abusing memory.

    One particularly handy feature is being able to drop into the debugger at the first sign of trouble (good for you), as opposed to your current situation of stumbling around until it finally crashes for no explainable reason.
    --vgdb=<no|yes|full> [default: yes]
    Valgrind will provide "gdbserver" functionality when --vgdb=yes or --vgdb=full is specified. This
    allows an external GNU GDB debugger to control and debug your program when it runs on Valgrind.
    --vgdb=full incurs significant performance overheads, but provides more precise breakpoints and
    watchpoints. See Debugging your program using Valgrind's gdbserver and GDB for a detailed description.
    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
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    thanks Salem,

    while I try to debug this with Valgrind,
    here is something I would like to share, hoping someone can identify some potential cause of problem.

    In the two functions, the structures are having different sizes. Using a utility function, I am printing data for structure in the two functions. a_function and b_function. Here is what I receive as output.


    Code:
    
    for (int i = 0 ; i < len ; i++ )
      {
            printf("[%03"PRIu8"]" , *(data + i) ) ;
      }
    
    
    
    // inside a_function()
    // calling utility_function(svp,sizeof(sv_t)
    // output is
    dumping: [003][000][000][000][047][000][000][000][196][001][000][000][196][001][000][000][000][000][000][000][000][000][000][000][002][000][000][000][001][000][000][000][002][000][000][000]
    
    // inside b_function()
    // calling utility_function(s,sizeof(sv_t)
    // output is
    dumping: [003][000][000][000][047][000][000][000][196][001][000][000][196][001][000][000][000][000][000][000][000][000][000][000][002][000][000][000]
    thanks,

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well the first obvious question would be why sizeof(sv_t) is apparently giving you 36 in one case and only 28 in the other.

    The common initial 28 bytes look like they compare identical, but the fact that sizeof() is giving different answers for apparently the same structure is bad news.

    Are you entirely sure that you compiled ALL your code after changing your struct?
    Bad makefile rules with incomplete dependencies lead to mis-matched object files (and the kind of weirdness you see).
    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
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    Hi Salem,

    thanks for your message.

    As a follow up to this question, I write something regarding compilation process, as I think, there may be the problem. Please, if you or someone can help in this regard. I wrote this to another forum specifically for cmake related question,


    I am building a simple project "my_application". I have all source (.c, and .h files) under "my_application". My CMakeLists.txt file is under "my_application".
    In this project, I need to link to a static library called "example_library.a".

    The way, I generate "example_library.a" is as follows. "example_library.a" needs some definition from "my_application". In the makefile which is used to generate "example_library.a" , I add the needed paths to "my_application". It compiles fine and result is "example_library.a".

    After linking to "example_library.a" in CMakeLists.txt, when I run cmake, it reports an error from linked static library.

    ~/IMPLEMENTATIONS/PollingServer/ftt-se/src/modules/ftt-core.layer/master/M_Server.h:5: error: my_types.h: No such file or directory
    #include "my_types.h"
    ^

    Please note that "my_types.h" is found under "my_application".


    Any ideas or pointers?


    thanks,

    zahid

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Please note that "my_types.h" is found under "my_application".
    Your library compilation command line needs

    -I/path/to/my_application (or whatever the subdirectory is where my_types.h is to be found).

    How you specify that in your make rules is up to you, I don't know your cmake scripts.
    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
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    thank you Salem,

    In order to explain this, I will write here the longer version that I wrote elsewhere. You can reply in your convenience. thanks for your time

    ================================================== ================================================== ================================

    For building my system, I am working with two directories. Let's call them my_application_directory and protocol_source_directory.

    The code relating to my application resides under my_application_directory. In fact, my application needs to interact with protocol_source_directory. My application needs some functions from protocol_source_directory as well as it can provide some functionality to some process that is within the protocol_source_directory.

    protocol_source_directory is an existing protocol suite with its own top-level makefile that compiles and builds the protocol and generates a static library. The directory structure for protocol_source_directory is as follows:

    protocol_source_directory
    |
    |___ dir1
    |
    |__ config
    |__ include
    |__ libs
    |__ misc
    |__ src
    |
    |__ modules
    | |
    | |__ layerA
    | |__ layerB
    | |__ layerC
    | |__ layerD
    |
    |
    |__ debug_tests
    |
    |__ my_application_directory

    Imagine a scenario in which there was no my_application_directory. In this case, protocol_source_directory builds and compiles with the makefile under protocol_source_directory/dir1. The static library generated (e.g. protocol_lib.a) is available under protocol_source_directory/dir1/libs/.

    Purpose of developing an application is to add some functionality in the protocol and then develop an application to test that functionality.

    To fulfill this purpose, new files are added,

    Few of new files are added at the location protocol_source_directory/dir1/src/modules/layerC/. There is a local makefile at this level which is updated to reflect these new files.
    some of the files need some definitions from my_application_directory. Therefore, I update the local makefile to include the needed paths to my_application_directory. so that I can use necessary headers inside ".c" files without path qualifiers.

    Having done this,

    protocol_source_directory builds and compiles with the makefile under protocol_source_directory/dir1 and generates the static library e.g. protocol_lib.a.

    Remaining functionality is implemented in files that reside under my_application_directory. It is important to note that my_application_directory can be at location protocol_source_directory/dir1/src/debug_tests/my_application_directory/ or it can exists separately at the same level as the protocol_source_directory

    Imagine a scenario where, my my_application_directory is separate (not inside) the protocol_source_directory. Here is the CMakeLists.txt that I am using to build my application while interacting with protocol source.

    Code:
    project(PS_TEST)
    cmake_minimum_required(VERSION 2.8)
    
    # manually adding the sources using the set command as follows:
    set(SRC_LIST main.c ISH.c ish_db.c ish_generator.c messages.c my_string_help.c populate_ish.c 
    ISH.h ish_db.h ish_generator.h messages.h my_string_help.h populate_ish.h my_types.h)
    add_executable(${PROJECT_NAME} ${SRC_LIST})
    
    # adding c99 style options
    set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 99)
    
    
    set(FTT_BASE protocol_source_directory/dir1)
    
    set(CORE_INCLUDES ${FTT_BASE}/src/modules/layerC/include/)
    set(ETH_INCLUDES ${FTT_BASE}/src/modules/layerA/include/)
    set(CORE_COMMONS ${FTT_BASE}/src/modules/layerC/common/)
    set(MASTER_INCLUDES ${FTT_BASE}/src/modules/layerC/master/)
    
    
    include_directories(include ${FTT_BASE}/config/ ${FTT_BASE}/misc/make-rules/ ${FTT_BASE}/misc/arch-ports/ ${CORE_INCLUDES} ${ETH_INCLUDES} ${CORE_COMMONS} ${MASTER_INCLUDES})
    add_definitions(${FTT_COMPILE_OPT}$)
    
    
    # linking to the protocl library code
    find_library (FTT_LIB protocol_lib.a protocol_source_directory/dir1/libs/)
    target_link_libraries(${PROJECT_NAME} ${FTT_LIB})
    Having done all this,

    when I build my application using cmake, it gives me the following error:

    my_types.h no such file and directory


    please note that my_types.h is in my_application_directory. But, since, some definitions are needed, I have included this file (i.e., include "my_types.h") in some .c files which are at protocol_source_directory/dir1/src/modules/layerC/.

    ================================================== ================================================== ================================================== =======

    Question: What I am doing wrong here, I have included the needed paths to my_application_directory, in the local makefile at protocol_source_directory/dir1/src/modules/layerC/. protocol_source_directory is compiling ok, why I receive this error after I link with static project libray.

    thanks,

    zahid

  14. #14
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    to answer briefly the previous comment,

    library compilation went smooth, as it did not complain and it was able to find the needed file. In the local makefile , I have included the paths:

    ifndef APPLICATION_PATH
    APPLICATION_PATH=../../../../../../PS_TEST/
    endif

    M_FLAGS += -I$(APPLICATION_PATH)/
    vpath %.h $(APPLICATION_PATH)/
    vpath %.c $(APPLICATION_PATH)/
    M_FLAGS += -I./../../../../../../PS_TEST/

  15. #15
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    Hi Salem,

    I am looking into this, and will write later on if I have another useful information.

    thanks for your help and time.

    Zahid

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Tic Tac Toe with enum. Assigning a char to an enum value.
    By Iceboxes in forum C++ Programming
    Replies: 6
    Last Post: 11-30-2013, 09:58 AM
  2. How do you handle enum checks in function arguments?
    By incorrect in forum C Programming
    Replies: 4
    Last Post: 08-31-2013, 05:36 PM
  3. class won't accept enum in a function
    By Roffemuffe in forum C++ Programming
    Replies: 8
    Last Post: 04-02-2011, 08:24 PM
  4. Replies: 1
    Last Post: 09-04-2007, 10:00 PM
  5. ENUM Function
    By Unregistered in forum C++ Programming
    Replies: 4
    Last Post: 12-10-2001, 07:13 PM

Tags for this Thread