Return statement does not get executed in c





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







3















So, I have a curious case and can't quite figure out what I've done wrong. Here's the scenario:



I have written a creator function that should return a pointer to a function. To fill the structure with data, I read in a text file. Depending on what text file I use as input, the error either occurs or it doesn't occur. (The error occurs for a text file with ~4000 lines and not for a file with ~200 if that makes a difference). The strange thing is that the code executes until right before the return statement. But it then does not return but just hangs. No errors, no compiler warnings (intel compiler). I wonder if anyone has experienced something similar or has an idea what could be going wrong.



The code below is simplified to illustrate the problem. The actual code is somewhat more complex since I'm using Schreiner's Approach to play with objects in C.



struct Somestruct {
int A;
int B;
int C;
}

static void *Somestruct_ctor(void *_self) {
struct Somestruct *self = _self;
fillDataFromFile(self);
printf("This line gets executed.n");
return self; // <- this one doesn't
}

int main(int argc, char *argv) {
void *myObject;

myObject = Somestruct_ctor(myObject);
printf("The code does NOT get until heren");
return 0;
}









share|improve this question




















  • 5





    void * myObject; is uninitialized. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject) is undefined behaviour. If your compiler doesn't warn about this by default, then enable warnings like gcc -Wall. You may need to enable optimization for the compiler to notice, e.g. gcc -Og -Wall. It may happen to be pointing somewhere on the stack, causing a buffer overflow that ends up in an infinite loop.

    – Peter Cordes
    Jan 3 at 3:17













  • C11 Standard - 6.3.2.1 Lvalues, arrays, and function designators(p1) An lvalue is an expression (with an object type other than void) that potentially designates an object;64) if an lvalue does not designate an object when it is evaluated, the behavior is undefined.

    – David C. Rankin
    Jan 3 at 3:38


















3















So, I have a curious case and can't quite figure out what I've done wrong. Here's the scenario:



I have written a creator function that should return a pointer to a function. To fill the structure with data, I read in a text file. Depending on what text file I use as input, the error either occurs or it doesn't occur. (The error occurs for a text file with ~4000 lines and not for a file with ~200 if that makes a difference). The strange thing is that the code executes until right before the return statement. But it then does not return but just hangs. No errors, no compiler warnings (intel compiler). I wonder if anyone has experienced something similar or has an idea what could be going wrong.



The code below is simplified to illustrate the problem. The actual code is somewhat more complex since I'm using Schreiner's Approach to play with objects in C.



struct Somestruct {
int A;
int B;
int C;
}

static void *Somestruct_ctor(void *_self) {
struct Somestruct *self = _self;
fillDataFromFile(self);
printf("This line gets executed.n");
return self; // <- this one doesn't
}

int main(int argc, char *argv) {
void *myObject;

myObject = Somestruct_ctor(myObject);
printf("The code does NOT get until heren");
return 0;
}









share|improve this question




















  • 5





    void * myObject; is uninitialized. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject) is undefined behaviour. If your compiler doesn't warn about this by default, then enable warnings like gcc -Wall. You may need to enable optimization for the compiler to notice, e.g. gcc -Og -Wall. It may happen to be pointing somewhere on the stack, causing a buffer overflow that ends up in an infinite loop.

    – Peter Cordes
    Jan 3 at 3:17













  • C11 Standard - 6.3.2.1 Lvalues, arrays, and function designators(p1) An lvalue is an expression (with an object type other than void) that potentially designates an object;64) if an lvalue does not designate an object when it is evaluated, the behavior is undefined.

    – David C. Rankin
    Jan 3 at 3:38














3












3








3








So, I have a curious case and can't quite figure out what I've done wrong. Here's the scenario:



I have written a creator function that should return a pointer to a function. To fill the structure with data, I read in a text file. Depending on what text file I use as input, the error either occurs or it doesn't occur. (The error occurs for a text file with ~4000 lines and not for a file with ~200 if that makes a difference). The strange thing is that the code executes until right before the return statement. But it then does not return but just hangs. No errors, no compiler warnings (intel compiler). I wonder if anyone has experienced something similar or has an idea what could be going wrong.



The code below is simplified to illustrate the problem. The actual code is somewhat more complex since I'm using Schreiner's Approach to play with objects in C.



struct Somestruct {
int A;
int B;
int C;
}

static void *Somestruct_ctor(void *_self) {
struct Somestruct *self = _self;
fillDataFromFile(self);
printf("This line gets executed.n");
return self; // <- this one doesn't
}

int main(int argc, char *argv) {
void *myObject;

myObject = Somestruct_ctor(myObject);
printf("The code does NOT get until heren");
return 0;
}









share|improve this question
















So, I have a curious case and can't quite figure out what I've done wrong. Here's the scenario:



I have written a creator function that should return a pointer to a function. To fill the structure with data, I read in a text file. Depending on what text file I use as input, the error either occurs or it doesn't occur. (The error occurs for a text file with ~4000 lines and not for a file with ~200 if that makes a difference). The strange thing is that the code executes until right before the return statement. But it then does not return but just hangs. No errors, no compiler warnings (intel compiler). I wonder if anyone has experienced something similar or has an idea what could be going wrong.



The code below is simplified to illustrate the problem. The actual code is somewhat more complex since I'm using Schreiner's Approach to play with objects in C.



struct Somestruct {
int A;
int B;
int C;
}

static void *Somestruct_ctor(void *_self) {
struct Somestruct *self = _self;
fillDataFromFile(self);
printf("This line gets executed.n");
return self; // <- this one doesn't
}

int main(int argc, char *argv) {
void *myObject;

myObject = Somestruct_ctor(myObject);
printf("The code does NOT get until heren");
return 0;
}






c return intel icc






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 3 at 4:16









chqrlie

62.5k848107




62.5k848107










asked Jan 3 at 3:07









Nathan FollyNathan Folly

223




223








  • 5





    void * myObject; is uninitialized. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject) is undefined behaviour. If your compiler doesn't warn about this by default, then enable warnings like gcc -Wall. You may need to enable optimization for the compiler to notice, e.g. gcc -Og -Wall. It may happen to be pointing somewhere on the stack, causing a buffer overflow that ends up in an infinite loop.

    – Peter Cordes
    Jan 3 at 3:17













  • C11 Standard - 6.3.2.1 Lvalues, arrays, and function designators(p1) An lvalue is an expression (with an object type other than void) that potentially designates an object;64) if an lvalue does not designate an object when it is evaluated, the behavior is undefined.

    – David C. Rankin
    Jan 3 at 3:38














  • 5





    void * myObject; is uninitialized. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject) is undefined behaviour. If your compiler doesn't warn about this by default, then enable warnings like gcc -Wall. You may need to enable optimization for the compiler to notice, e.g. gcc -Og -Wall. It may happen to be pointing somewhere on the stack, causing a buffer overflow that ends up in an infinite loop.

    – Peter Cordes
    Jan 3 at 3:17













  • C11 Standard - 6.3.2.1 Lvalues, arrays, and function designators(p1) An lvalue is an expression (with an object type other than void) that potentially designates an object;64) if an lvalue does not designate an object when it is evaluated, the behavior is undefined.

    – David C. Rankin
    Jan 3 at 3:38








5




5





void * myObject; is uninitialized. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject) is undefined behaviour. If your compiler doesn't warn about this by default, then enable warnings like gcc -Wall. You may need to enable optimization for the compiler to notice, e.g. gcc -Og -Wall. It may happen to be pointing somewhere on the stack, causing a buffer overflow that ends up in an infinite loop.

– Peter Cordes
Jan 3 at 3:17







void * myObject; is uninitialized. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject) is undefined behaviour. If your compiler doesn't warn about this by default, then enable warnings like gcc -Wall. You may need to enable optimization for the compiler to notice, e.g. gcc -Og -Wall. It may happen to be pointing somewhere on the stack, causing a buffer overflow that ends up in an infinite loop.

– Peter Cordes
Jan 3 at 3:17















C11 Standard - 6.3.2.1 Lvalues, arrays, and function designators(p1) An lvalue is an expression (with an object type other than void) that potentially designates an object;64) if an lvalue does not designate an object when it is evaluated, the behavior is undefined.

– David C. Rankin
Jan 3 at 3:38





C11 Standard - 6.3.2.1 Lvalues, arrays, and function designators(p1) An lvalue is an expression (with an object type other than void) that potentially designates an object;64) if an lvalue does not designate an object when it is evaluated, the behavior is undefined.

– David C. Rankin
Jan 3 at 3:38












1 Answer
1






active

oldest

votes


















10














void * myObject; is uninitialized, and not pointing at valid storage. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject)) is undefined behaviour.



The fact that your code doesn't always crash tells us that in ICC's code-gen it happens to be pointing somewhere valid, probably somewhere on the stack. With a larger file, we presumably get a buffer overflow that overwrites a local variable and/or a return address and ends up in an infinite loop. It's pretty amazing that this managed to still not crash given that it happened by accident. (In the x86-64 asm from ICC with optimization disabled, it just loads some uninitialized stack memory as an arg for Somestruct_ctor.)



Or maybe its a pointer to a stdio data structure, left over from init of stdio before main. Perhaps having fillDataFromFile scribble all over the data that FILE *stdout points to (for example) left it in a "locked" state, so your single thread is stuck waiting for something else to unlock a mutex. If you know asm, it might be interesting to single-step the infinite loop or "deadlock" inside printf and see exactly what happened.





If you compile with gcc -O3, the compiler zeros a register as an arg for fillDataFromFile (after inlining Somestruct_ctor), so it's passing a NULL pointer. That would presumably crash always, assuming the function dereferences the pointer.



clang chooses to leave rdi (the first arg-passing register in the x86-64 System V calling conventino) uninitialized, so it still holds argc when main calls fillDataFromFile. That would also reliably crash.





You forgot to enable compiler warnings.



All the major x86 compilers (gcc, clang, MSVC, ICC) have warnings for this, but they aren't on by default in all compilers (only in MSVC). Probably because there can be cases where the compiler isn't sure about a var being uninitialized if there's some conditional stuff. In this case it's 100% certain that it's definitely used uninitialized, but if the init and the use were inside different if() blocks, the compiler might not be able to prove that the use only happened if the init happened.



With clang and gcc, you should usually use -Wall and silence all the warnings.



With ICC, -diag-enable:warn is closer to gcc -Wall. (ICC's -Wall doesn't enable this very important warning. Don't be fooled into thinking you've enabled all important warnings with icc -Wall.)



 # from icc -diag-enable:warn on your code
<source>(21): warning #592: variable "myObject" is used before its value is set
myObject = Somestruct_ctor(myObject);
^


how to turn on icc/icpc warnings? has some info. It ways that icc's -Wall is very minimalisitc compared to gcc's. So maybe -Wall -Wextra would be useful with icc. It recommends -w2 or -w3 as potentially-useful warning levels.





Clang usually has the nicest warnings, in this case:



<source>:21:30: warning: variable 'myObject' is uninitialized when used here [-Wuninitialized]
myObject = Somestruct_ctor(myObject);
^~~~~~~~
<source>:19:18: note: initialize the variable 'myObject' to silence this warning
void * myObject;
^
= NULL
1 warning generated.




I got the above outputs by compiling your source on the Godbolt compiler explorer (after fixing the syntax errors: missing semicolon after the struct, and the capitalization of the Struct keyword.) -xc tells the C++ compilers on Godbolt to compile as C.



It turns out that you don't need to enable optimization for icc and gcc to notice this error. Some warnings only work with optimization enabled, where the compiler does more analysis of program logic and can notice more, but they track uninitialized even at -O0.





constructor code that would make more sense:



// C
int main(void){
struct Somestruct myObject; // automatic storage for the object value
Somestruct_ctor(&myObject); // pass a pointer to that storage
}


The object needs to live somewhere. We can get space for it with automatic (a local), static (a static local, or a global), or dynamic storage (malloc).



Automatic storage + calling the constructor is equivalent to C++ like this, if struct Somestruct has a C++ default constructor declared in the struct/class definition.



// C++
int main(void){
Somestruct myObject; // calls the default constructor, if there is one
// destructor will be called at some point when myObject goes out of scope
}





share|improve this answer


























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015817%2freturn-statement-does-not-get-executed-in-c%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    10














    void * myObject; is uninitialized, and not pointing at valid storage. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject)) is undefined behaviour.



    The fact that your code doesn't always crash tells us that in ICC's code-gen it happens to be pointing somewhere valid, probably somewhere on the stack. With a larger file, we presumably get a buffer overflow that overwrites a local variable and/or a return address and ends up in an infinite loop. It's pretty amazing that this managed to still not crash given that it happened by accident. (In the x86-64 asm from ICC with optimization disabled, it just loads some uninitialized stack memory as an arg for Somestruct_ctor.)



    Or maybe its a pointer to a stdio data structure, left over from init of stdio before main. Perhaps having fillDataFromFile scribble all over the data that FILE *stdout points to (for example) left it in a "locked" state, so your single thread is stuck waiting for something else to unlock a mutex. If you know asm, it might be interesting to single-step the infinite loop or "deadlock" inside printf and see exactly what happened.





    If you compile with gcc -O3, the compiler zeros a register as an arg for fillDataFromFile (after inlining Somestruct_ctor), so it's passing a NULL pointer. That would presumably crash always, assuming the function dereferences the pointer.



    clang chooses to leave rdi (the first arg-passing register in the x86-64 System V calling conventino) uninitialized, so it still holds argc when main calls fillDataFromFile. That would also reliably crash.





    You forgot to enable compiler warnings.



    All the major x86 compilers (gcc, clang, MSVC, ICC) have warnings for this, but they aren't on by default in all compilers (only in MSVC). Probably because there can be cases where the compiler isn't sure about a var being uninitialized if there's some conditional stuff. In this case it's 100% certain that it's definitely used uninitialized, but if the init and the use were inside different if() blocks, the compiler might not be able to prove that the use only happened if the init happened.



    With clang and gcc, you should usually use -Wall and silence all the warnings.



    With ICC, -diag-enable:warn is closer to gcc -Wall. (ICC's -Wall doesn't enable this very important warning. Don't be fooled into thinking you've enabled all important warnings with icc -Wall.)



     # from icc -diag-enable:warn on your code
    <source>(21): warning #592: variable "myObject" is used before its value is set
    myObject = Somestruct_ctor(myObject);
    ^


    how to turn on icc/icpc warnings? has some info. It ways that icc's -Wall is very minimalisitc compared to gcc's. So maybe -Wall -Wextra would be useful with icc. It recommends -w2 or -w3 as potentially-useful warning levels.





    Clang usually has the nicest warnings, in this case:



    <source>:21:30: warning: variable 'myObject' is uninitialized when used here [-Wuninitialized]
    myObject = Somestruct_ctor(myObject);
    ^~~~~~~~
    <source>:19:18: note: initialize the variable 'myObject' to silence this warning
    void * myObject;
    ^
    = NULL
    1 warning generated.




    I got the above outputs by compiling your source on the Godbolt compiler explorer (after fixing the syntax errors: missing semicolon after the struct, and the capitalization of the Struct keyword.) -xc tells the C++ compilers on Godbolt to compile as C.



    It turns out that you don't need to enable optimization for icc and gcc to notice this error. Some warnings only work with optimization enabled, where the compiler does more analysis of program logic and can notice more, but they track uninitialized even at -O0.





    constructor code that would make more sense:



    // C
    int main(void){
    struct Somestruct myObject; // automatic storage for the object value
    Somestruct_ctor(&myObject); // pass a pointer to that storage
    }


    The object needs to live somewhere. We can get space for it with automatic (a local), static (a static local, or a global), or dynamic storage (malloc).



    Automatic storage + calling the constructor is equivalent to C++ like this, if struct Somestruct has a C++ default constructor declared in the struct/class definition.



    // C++
    int main(void){
    Somestruct myObject; // calls the default constructor, if there is one
    // destructor will be called at some point when myObject goes out of scope
    }





    share|improve this answer






























      10














      void * myObject; is uninitialized, and not pointing at valid storage. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject)) is undefined behaviour.



      The fact that your code doesn't always crash tells us that in ICC's code-gen it happens to be pointing somewhere valid, probably somewhere on the stack. With a larger file, we presumably get a buffer overflow that overwrites a local variable and/or a return address and ends up in an infinite loop. It's pretty amazing that this managed to still not crash given that it happened by accident. (In the x86-64 asm from ICC with optimization disabled, it just loads some uninitialized stack memory as an arg for Somestruct_ctor.)



      Or maybe its a pointer to a stdio data structure, left over from init of stdio before main. Perhaps having fillDataFromFile scribble all over the data that FILE *stdout points to (for example) left it in a "locked" state, so your single thread is stuck waiting for something else to unlock a mutex. If you know asm, it might be interesting to single-step the infinite loop or "deadlock" inside printf and see exactly what happened.





      If you compile with gcc -O3, the compiler zeros a register as an arg for fillDataFromFile (after inlining Somestruct_ctor), so it's passing a NULL pointer. That would presumably crash always, assuming the function dereferences the pointer.



      clang chooses to leave rdi (the first arg-passing register in the x86-64 System V calling conventino) uninitialized, so it still holds argc when main calls fillDataFromFile. That would also reliably crash.





      You forgot to enable compiler warnings.



      All the major x86 compilers (gcc, clang, MSVC, ICC) have warnings for this, but they aren't on by default in all compilers (only in MSVC). Probably because there can be cases where the compiler isn't sure about a var being uninitialized if there's some conditional stuff. In this case it's 100% certain that it's definitely used uninitialized, but if the init and the use were inside different if() blocks, the compiler might not be able to prove that the use only happened if the init happened.



      With clang and gcc, you should usually use -Wall and silence all the warnings.



      With ICC, -diag-enable:warn is closer to gcc -Wall. (ICC's -Wall doesn't enable this very important warning. Don't be fooled into thinking you've enabled all important warnings with icc -Wall.)



       # from icc -diag-enable:warn on your code
      <source>(21): warning #592: variable "myObject" is used before its value is set
      myObject = Somestruct_ctor(myObject);
      ^


      how to turn on icc/icpc warnings? has some info. It ways that icc's -Wall is very minimalisitc compared to gcc's. So maybe -Wall -Wextra would be useful with icc. It recommends -w2 or -w3 as potentially-useful warning levels.





      Clang usually has the nicest warnings, in this case:



      <source>:21:30: warning: variable 'myObject' is uninitialized when used here [-Wuninitialized]
      myObject = Somestruct_ctor(myObject);
      ^~~~~~~~
      <source>:19:18: note: initialize the variable 'myObject' to silence this warning
      void * myObject;
      ^
      = NULL
      1 warning generated.




      I got the above outputs by compiling your source on the Godbolt compiler explorer (after fixing the syntax errors: missing semicolon after the struct, and the capitalization of the Struct keyword.) -xc tells the C++ compilers on Godbolt to compile as C.



      It turns out that you don't need to enable optimization for icc and gcc to notice this error. Some warnings only work with optimization enabled, where the compiler does more analysis of program logic and can notice more, but they track uninitialized even at -O0.





      constructor code that would make more sense:



      // C
      int main(void){
      struct Somestruct myObject; // automatic storage for the object value
      Somestruct_ctor(&myObject); // pass a pointer to that storage
      }


      The object needs to live somewhere. We can get space for it with automatic (a local), static (a static local, or a global), or dynamic storage (malloc).



      Automatic storage + calling the constructor is equivalent to C++ like this, if struct Somestruct has a C++ default constructor declared in the struct/class definition.



      // C++
      int main(void){
      Somestruct myObject; // calls the default constructor, if there is one
      // destructor will be called at some point when myObject goes out of scope
      }





      share|improve this answer




























        10












        10








        10







        void * myObject; is uninitialized, and not pointing at valid storage. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject)) is undefined behaviour.



        The fact that your code doesn't always crash tells us that in ICC's code-gen it happens to be pointing somewhere valid, probably somewhere on the stack. With a larger file, we presumably get a buffer overflow that overwrites a local variable and/or a return address and ends up in an infinite loop. It's pretty amazing that this managed to still not crash given that it happened by accident. (In the x86-64 asm from ICC with optimization disabled, it just loads some uninitialized stack memory as an arg for Somestruct_ctor.)



        Or maybe its a pointer to a stdio data structure, left over from init of stdio before main. Perhaps having fillDataFromFile scribble all over the data that FILE *stdout points to (for example) left it in a "locked" state, so your single thread is stuck waiting for something else to unlock a mutex. If you know asm, it might be interesting to single-step the infinite loop or "deadlock" inside printf and see exactly what happened.





        If you compile with gcc -O3, the compiler zeros a register as an arg for fillDataFromFile (after inlining Somestruct_ctor), so it's passing a NULL pointer. That would presumably crash always, assuming the function dereferences the pointer.



        clang chooses to leave rdi (the first arg-passing register in the x86-64 System V calling conventino) uninitialized, so it still holds argc when main calls fillDataFromFile. That would also reliably crash.





        You forgot to enable compiler warnings.



        All the major x86 compilers (gcc, clang, MSVC, ICC) have warnings for this, but they aren't on by default in all compilers (only in MSVC). Probably because there can be cases where the compiler isn't sure about a var being uninitialized if there's some conditional stuff. In this case it's 100% certain that it's definitely used uninitialized, but if the init and the use were inside different if() blocks, the compiler might not be able to prove that the use only happened if the init happened.



        With clang and gcc, you should usually use -Wall and silence all the warnings.



        With ICC, -diag-enable:warn is closer to gcc -Wall. (ICC's -Wall doesn't enable this very important warning. Don't be fooled into thinking you've enabled all important warnings with icc -Wall.)



         # from icc -diag-enable:warn on your code
        <source>(21): warning #592: variable "myObject" is used before its value is set
        myObject = Somestruct_ctor(myObject);
        ^


        how to turn on icc/icpc warnings? has some info. It ways that icc's -Wall is very minimalisitc compared to gcc's. So maybe -Wall -Wextra would be useful with icc. It recommends -w2 or -w3 as potentially-useful warning levels.





        Clang usually has the nicest warnings, in this case:



        <source>:21:30: warning: variable 'myObject' is uninitialized when used here [-Wuninitialized]
        myObject = Somestruct_ctor(myObject);
        ^~~~~~~~
        <source>:19:18: note: initialize the variable 'myObject' to silence this warning
        void * myObject;
        ^
        = NULL
        1 warning generated.




        I got the above outputs by compiling your source on the Godbolt compiler explorer (after fixing the syntax errors: missing semicolon after the struct, and the capitalization of the Struct keyword.) -xc tells the C++ compilers on Godbolt to compile as C.



        It turns out that you don't need to enable optimization for icc and gcc to notice this error. Some warnings only work with optimization enabled, where the compiler does more analysis of program logic and can notice more, but they track uninitialized even at -O0.





        constructor code that would make more sense:



        // C
        int main(void){
        struct Somestruct myObject; // automatic storage for the object value
        Somestruct_ctor(&myObject); // pass a pointer to that storage
        }


        The object needs to live somewhere. We can get space for it with automatic (a local), static (a static local, or a global), or dynamic storage (malloc).



        Automatic storage + calling the constructor is equivalent to C++ like this, if struct Somestruct has a C++ default constructor declared in the struct/class definition.



        // C++
        int main(void){
        Somestruct myObject; // calls the default constructor, if there is one
        // destructor will be called at some point when myObject goes out of scope
        }





        share|improve this answer















        void * myObject; is uninitialized, and not pointing at valid storage. Reading its value (to pass it as an arg by value to Somestruct_ctor(myObject)) is undefined behaviour.



        The fact that your code doesn't always crash tells us that in ICC's code-gen it happens to be pointing somewhere valid, probably somewhere on the stack. With a larger file, we presumably get a buffer overflow that overwrites a local variable and/or a return address and ends up in an infinite loop. It's pretty amazing that this managed to still not crash given that it happened by accident. (In the x86-64 asm from ICC with optimization disabled, it just loads some uninitialized stack memory as an arg for Somestruct_ctor.)



        Or maybe its a pointer to a stdio data structure, left over from init of stdio before main. Perhaps having fillDataFromFile scribble all over the data that FILE *stdout points to (for example) left it in a "locked" state, so your single thread is stuck waiting for something else to unlock a mutex. If you know asm, it might be interesting to single-step the infinite loop or "deadlock" inside printf and see exactly what happened.





        If you compile with gcc -O3, the compiler zeros a register as an arg for fillDataFromFile (after inlining Somestruct_ctor), so it's passing a NULL pointer. That would presumably crash always, assuming the function dereferences the pointer.



        clang chooses to leave rdi (the first arg-passing register in the x86-64 System V calling conventino) uninitialized, so it still holds argc when main calls fillDataFromFile. That would also reliably crash.





        You forgot to enable compiler warnings.



        All the major x86 compilers (gcc, clang, MSVC, ICC) have warnings for this, but they aren't on by default in all compilers (only in MSVC). Probably because there can be cases where the compiler isn't sure about a var being uninitialized if there's some conditional stuff. In this case it's 100% certain that it's definitely used uninitialized, but if the init and the use were inside different if() blocks, the compiler might not be able to prove that the use only happened if the init happened.



        With clang and gcc, you should usually use -Wall and silence all the warnings.



        With ICC, -diag-enable:warn is closer to gcc -Wall. (ICC's -Wall doesn't enable this very important warning. Don't be fooled into thinking you've enabled all important warnings with icc -Wall.)



         # from icc -diag-enable:warn on your code
        <source>(21): warning #592: variable "myObject" is used before its value is set
        myObject = Somestruct_ctor(myObject);
        ^


        how to turn on icc/icpc warnings? has some info. It ways that icc's -Wall is very minimalisitc compared to gcc's. So maybe -Wall -Wextra would be useful with icc. It recommends -w2 or -w3 as potentially-useful warning levels.





        Clang usually has the nicest warnings, in this case:



        <source>:21:30: warning: variable 'myObject' is uninitialized when used here [-Wuninitialized]
        myObject = Somestruct_ctor(myObject);
        ^~~~~~~~
        <source>:19:18: note: initialize the variable 'myObject' to silence this warning
        void * myObject;
        ^
        = NULL
        1 warning generated.




        I got the above outputs by compiling your source on the Godbolt compiler explorer (after fixing the syntax errors: missing semicolon after the struct, and the capitalization of the Struct keyword.) -xc tells the C++ compilers on Godbolt to compile as C.



        It turns out that you don't need to enable optimization for icc and gcc to notice this error. Some warnings only work with optimization enabled, where the compiler does more analysis of program logic and can notice more, but they track uninitialized even at -O0.





        constructor code that would make more sense:



        // C
        int main(void){
        struct Somestruct myObject; // automatic storage for the object value
        Somestruct_ctor(&myObject); // pass a pointer to that storage
        }


        The object needs to live somewhere. We can get space for it with automatic (a local), static (a static local, or a global), or dynamic storage (malloc).



        Automatic storage + calling the constructor is equivalent to C++ like this, if struct Somestruct has a C++ default constructor declared in the struct/class definition.



        // C++
        int main(void){
        Somestruct myObject; // calls the default constructor, if there is one
        // destructor will be called at some point when myObject goes out of scope
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 3 at 4:07

























        answered Jan 3 at 3:48









        Peter CordesPeter Cordes

        134k18203342




        134k18203342
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015817%2freturn-statement-does-not-get-executed-in-c%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

            Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

            A Topological Invariant for $pi_3(U(n))$