Like Tree1Likes

This compiles!..but segfaults. (Defining main as a functor)

This is a discussion on This compiles!..but segfaults. (Defining main as a functor) within the C++ Programming forums, part of the General Programming Boards category; Though I can't see any application for this... Code: class Foo { public: int operator()(){return 0;} }; Foo main; I ...

  1. #1
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498

    This compiles!..but segfaults. (Defining main as a functor)

    Though I can't see any application for this...
    Code:
    class Foo
    {
    public:
        int operator()(){return 0;}
    };
    Foo main;
    I was quite surprised to see this compile without a single warning.
    But unfortunately...it gives a segfault as soon as it begins running (and gdb downright refuses to help me track it).
    Any idea of something...say.. calling conventions... that can be modified to make this work ?

    P.S : I have evidence(in the form of putting a print statement in Foo's ctor) that "main" is created before the segfault occurs.
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



  2. #2
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,230
    There are a couple reasons that won't work. But consider this -- the runtime is a binary component, already compiled. How could it possibly know that your main() is actually a functor? It hasn't seen any of your declarations and could not possibly have a clue about it.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498
    True... this
    Code:
    int main;
    compiles too.
    Shouldn't this be classified as a compiler bug ?
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



  4. #4
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,230
    Maybe. The compiler can't outright forbid it, because people use compilers to write very non-standard bits of code from time to time. The linker just wants to bind some symbol called "main" -- you provided one, so the linker has nothing to complain about. Unfortunately the symbol is actually a piece of data, not a function, so it pops.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,417
    This will also compile
    Code:
    int main[] = { 1, 2, 3, };
    but it doesn't mean that it will in any shape or form run (well it might, if you list actual opcodes in the array).

    The linker just doesn't care about anything apart from symbol names. It looks for something called 'main' to call, and as soon as it sees such a symbol, it's happy.
    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.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    Quote Originally Posted by manasij7479
    Shouldn't this be classified as a compiler bug ?
    What do you consider to be the correct behaviour? My opinion is that the behaviour is undefined whether you define main as a functor or as a variable in the global namespace, so no matter what happens, there is no compiler bug.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498
    Quote Originally Posted by Salem View Post
    This will also compile
    (well it might, if you list actual opcodes in the array).
    Seems like a good thing to try out.
    What would be the numbers for putting 1 in eax , 0 in ebx and invoking the kernel for exit be ?
    Last edited by manasij7479; 12-05-2011 at 09:14 PM.
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



  8. #8
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,230
    Quote Originally Posted by manasij7479 View Post
    > (well it might, if you list actual opcodes in the array)
    Seems like a good thing to try out.

    What would be the numbers for putting 1 into eax , 0 in ebx and invoking the kernel for exit be ?
    It wouldn't work. Such an object would be data, and would be placed in the data segment, which is non-executable. It would crash the moment it jumped to it.

    EDIT: But if you do want to try it, you can use:

    Code:
    unsigned char main[] = { 0xBB, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xCD, 0x80 };
    Last edited by brewbuck; 12-05-2011 at 09:15 PM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498
    Doesn't crash..!!
    ...and the shell shows that it really returns 0.

    Does the array get placed into the code segment or is it just an accident ?

    Gah.. I can't make sense of the assembly ...but it seems to be store as data... and not as code...right?..
    Code:
        .file    "a.c"
        .globl    main
        .data
        .type    main, @object
        .size    main, 12
    main:
        .byte    -69
        .byte    0
        .byte    0
        .byte    0
        .byte    0
        .byte    -72
        .byte    1
        .byte    0
        .byte    0
        .byte    0
        .byte    -51
        .byte    -128
        .ident    "GCC: (GNU) 4.6.2 20111027 (Red Hat 4.6.2-1)"
        .section    .note.GNU-stack,"",@progbits
    Last edited by manasij7479; 12-05-2011 at 09:36 PM.
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



  10. #10
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,230
    Yeah, it's going into the data segment. It's strange if it's really executing. If you change 0xBB, 0x00 to 0xBB, 0x01 does the return code change from 0 to 1?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  11. #11
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498
    Quote Originally Posted by brewbuck View Post
    Yeah, it's going into the data segment. It's strange if it's really executing. If you change 0xBB, 0x00 to 0xBB, 0x01 does the return code change from 0 to 1?
    Yes ..it does.
    [manasij7479@manasijn code]$ gcc a.c -o a
    [manasij7479@manasijn code]$ ./a
    [manasij7479@manasijn code]$ echo $?
    1
    [manasij7479@manasijn code]$
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,163
    Apart from being the name of the entry point for a program (assuming a hosted implementation) the name main is not reserved. It is therefore possible to have member functions, enumerations, and even classes named main. That is why your code compiles.

    However, it is not possible to have an object (or a variable) and a function with the same name declared in a compilation unit, unless they are in different namespaces.

    A static object (even one named main) will always be constructed before the main() function is called. However, the operator() for such an object will not be called unless you write code to call it. If the object is named main, that is not possible from the main() function: you will need to write another function, to be called by the main() function, that - in turn - calls operator() for the object named main.

    There is nothing wrong with the fact your code compiles. Even though the code is meaningless. The linker, when it sees an object named main, probably matches it incorrectly with the main() function called during program startup. Hence, during program startup, it tries to treat the object itself (not the operator()) like a function. Since the object is not a function, trying to call it randomly access some area of memory. Hence your segmentation fault.

    Strictly speaking, your code does not exhibit undefined behaviour. However, it is an edge case that fails basic sanity checks. The standard committee probably never anticipated it or, if they did, assumed no programmer would be stupid or insane enough to attempt such code. Which goes to show: no standard is fool proof.
    Right 98% of the time, and don't care about the other 3%.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    Quote Originally Posted by grumpy
    Apart from being the name of the entry point for a program (assuming a hosted implementation) the name main is not reserved. It is therefore possible to have member functions, enumerations, and even classes named main.
    Quote Originally Posted by grumpy
    Strictly speaking, your code does not exhibit undefined behaviour.
    The standard states:
    Quote Originally Posted by C++11 Clause 3.6.1 Paragraph 1a
    A program shall contain a global function called main, which is the designated start of the program.
    I posit that this means that indeed the name main can be used to name enumerations, classes, etc, except in the global namespace (and std, but that's another matter). This is why my opinion is that the behaviour is undefined.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498
    Quote Originally Posted by grumpy View Post
    ... it tries to treat the object itself (not the operator()) like a function. Since the object is not a function, trying to call it randomly access some area of memory. Hence your segmentation fault.
    I used to know that calling the symbol associated with an object points to the () operator function.. but it is (now) clear that it is not the case.
    Last edited by manasij7479; 12-06-2011 at 12:02 AM.
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



  15. #15
    Registered User manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    Kolkata@India
    Posts
    2,498
    Quote Originally Posted by laserlight View Post
    The standard states...
    I think that also means that whenever a compiler finds something called main in global scope...it'll take it as a function...(evident from executing the array above ...giving consistent results with the 2 compilers I tried)
    Manasij Mukherjee | gcc-4.8.2 @Arch Linux
    Slow and Steady wins the race... if and only if :
    1.None of the other participants are fast and steady.
    2.The fast and unsteady suddenly falls asleep while running !



Page 1 of 3 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. help with a functor
    By nullspace in forum C++ Programming
    Replies: 1
    Last Post: 08-25-2011, 11:12 PM
  2. Defining functions below int main() - Best practices?
    By Programmer_P in forum C++ Programming
    Replies: 17
    Last Post: 12-09-2009, 01:08 PM
  3. Defining functions outside main - problem
    By helpmeout in forum C++ Programming
    Replies: 16
    Last Post: 03-22-2006, 01:06 AM
  4. Defining main function!
    By alvifarooq in forum C++ Programming
    Replies: 8
    Last Post: 09-19-2004, 02:00 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21