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

  1. #16
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by laserlight View Post
    The standard states:
    <quote snipped>
    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).
    Two paragraphs further down (I only have the 1998 C++ standard handy, but IIRC the same words are in C++-11)

    Quote Originally Posted by C++ 1998
    The function main shall not be used (3.2) within a program. The linkage (3.5) of main is implementation defined. A program that declares main to be inline or static is ill formed. The name main is not otherwise reserved. [Example: member functions, classes, and enumerations can be called main, as can entities in other namespaces. ]
    Quote Originally Posted by laserlight View Post
    This is why my opinion is that the behaviour is undefined.
    My view is that the content of the standard is a bit too ambiguous to either support or refute that opinion. I think we can safely agree, informally, it is not a good thing to do
    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.

  2. #17
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    One could of course have your entire program execute in a blocking manner within a constructor of a static object, and exit(0) instead of returning a value from main, never ever actually reaching main at any time *. That way it wouldn't matter what main was.
    Of course you would have to have no other globals with constructors or they might not have run yet.

    * It might work, but that's not to say it's ever a good idea.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #18
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Just an interesting note... Visual Studio refuses to compile the code.
    "unresolved external symbol main."
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #19
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    You sure that is not a linker error, or equivalent, Elysia?
    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.

  5. #20
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    'Shall' in the standard is a definitive requirement, yielding ill-formed programs if violated. Every usage of the word shows this. Therefore laserlight's quote is unambiguous: a program that does not contain a global function called main is ill-formed, diagnostic required from a strictly conforming implementation. The fact that only the linker may be able to issue such a diagnostic only means that the linker has to - as far as the standard is concerned, the linker (and even the loader) is part of the implementation.
    However, that GCC won't diagnose a global object called main is pretty definitely a bug - probably forced by weirdness in ancient C programs.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  6. #21
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by grumpy View Post
    You sure that is not a linker error, or equivalent, Elysia?
    Yeah, it is a linking error.
    Perhaps that was a bit unambiguous. When we speak of compile, we typically mean that the resulting program turns into an executable, which is not the case here.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #22
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by brewbuck View Post
    It would crash the moment it jumped to it.
    only if data and code segments occupy different regions of virtual memory (strictly speaking of x86-based architecture in this case). windows and linux (and probably most other operating systems on x86 architecture) map code and data segments to the same virtual memory space, so a call to data is still a near call, and if the data contains executable code, it will run until it encounters an error, which in this case, it does not. this is the same reason why function pointers can be used interchangeably with other types of pointers.

  8. #23
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by Elkvis View Post
    this is the same reason why function pointers can be used interchangeably with other types of pointers.
    Would that remain true..according to your explanation -- "if data and code segments occupy different regions of virtual memory" ?

  9. #24
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    the compiler would have to be able to handle "far" pointers - pointers to data in other segments that include the segment and offset, but it could still be made to work. a far pointer would likely be 48 bits on 32-bit x86 or 80 bits on x86-64, but there's no reason why it couldn't be made to work, and I'm sure there are platforms where they do exactly that.

  10. #25
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elkvis View Post
    only if data and code segments occupy different regions of virtual memory (strictly speaking of x86-based architecture in this case). windows and linux (and probably most other operating systems on x86 architecture) map code and data segments to the same virtual memory space, so a call to data is still a near call, and if the data contains executable code, it will run until it encounters an error, which in this case, it does not. this is the same reason why function pointers can be used interchangeably with other types of pointers.
    On Linux, no way. The data segment most certainly should not be executable. And by "segment" I mean a region of pages defined in the ELF header to be data, and not executable. Not segment in the sense of an x86 segment register, which neither Windows nor Linux make much use of.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  11. #26
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by CornedBee View Post
    'Shall' in the standard is a definitive requirement, yielding ill-formed programs if violated. Every usage of the word shows this. Therefore laserlight's quote is unambiguous: a program that does not contain a global function called main is ill-formed, diagnostic required from a strictly conforming implementation. The fact that only the linker may be able to issue such a diagnostic only means that the linker has to - as far as the standard is concerned, the linker (and even the loader) is part of the implementation.
    Sure, but "ill-formed" is not the same as "exhibiting undefined behaviour", which was laserlight's conclusion.
    Quote Originally Posted by CornedBee View Post
    However, that GCC won't diagnose a global object called main is pretty definitely a bug - probably forced by weirdness in ancient C programs.
    The section I quoted from the C++ standard also states flatly that the name main is not reserved (other than requiring that main() not be declared static or inline). From that it may be concluded that the compiler is not required to issue a diagnostic when the name is used.

    Given that the absence of a main() function (or duplication, for that matter) can only reasonably be detected by a linker (i.e. post-compilation) it is not reasonable to expect a C++ compiler (when working with separately source files) to diagnose it.
    Last edited by grumpy; 12-07-2011 at 01:50 AM.
    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.

  12. #27
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by grumpy
    Sure, but "ill-formed" is not the same as "exhibiting undefined behaviour", which was laserlight's conclusion.
    Agreed.

    Quote Originally Posted by grumpy
    The section I quoted from the C++ standard also states flatly that the name main is not reserved (other than requiring that main() not be declared static or inline). From that it may be concluded that the compiler is not required to issue a diagnostic when the name is used.
    The word "function" is used though, so it could be interpreted as "the name main in global scope must be the name of a function".
    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

  13. #28
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by grumpy View Post
    Sure, but "ill-formed" is not the same as "exhibiting undefined behaviour", which was laserlight's conclusion.
    If the implementation produces an executable for an ill-formed program, what else would it be but undefined?

    The section I quoted from the C++ standard also states flatly that the name main is not reserved (other than requiring that main() not be declared static or inline).
    Most importantly, other than being a global function with return type int, as paragraphs 1 & 2 of that section require. By simple exclusion, if there is a global non-static function called main, there cannot be anything else in the same namespace with external linkage called main - or at least it must not be treated as the entry point.

    From that it may be concluded that the compiler is not required to issue a diagnostic when the name is used.
    Either an implementation provides a linking scheme where a global function called main and a global object called main can be distinguished (as seems to be the case for VC++), or (if C functions and objects have the same mangling, as seems to be the case with GCC) it must forbid declaring global objects called main. Anything else is a conformance issue.

    Given that the absence of a main() function (or duplication, for that matter) can only reasonably be detected by a linker (i.e. post-compilation) it is not reasonable to expect a C++ compiler (when working with separately source files) to diagnose it.
    I'm fine with a linker error. But there must be *some* error.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  14. #29
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by laserlight View Post
    The word "function" is used though, so it could be interpreted as "the name main in global scope must be the name of a function".
    Yeah, maybe, but I'm doubtful.

    It is possible to have a global of some other name (let's say x) at global scope in one source file, and another name (say x()) at global scope in another file. I see nothing in the section on main() that prevents such things.

    That said, I would be quite happy to get a diagnostic (from either compiler compiler or linker) upon an attempt to create something at global scope called main(). I just doubt it is required.

    Incidentally, I'm using mingw, and get a linker error if I have an int named main() at global scope in one file, and the main() function in another.
    Last edited by grumpy; 12-07-2011 at 03:16 AM.
    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.

  15. #30
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by CornedBee View Post
    If the implementation produces an executable for an ill-formed program, what else would it be but undefined?
    It is an ill-formed program that produces an executable

    The notions of ill-formed program and undefined behaviour intersect in the standard, but are not equivalent.

    It is possible to have a well-formed program that exhibits undefined behaviour, and it is possible to have an ill-formed program for which no diagnostics are required. Practically, linkers typically produces a diagnostic when they refuse to (or cannot) produce an executable as output.
    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. 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, 02:08 PM
  3. Defining functions outside main - problem
    By helpmeout in forum C++ Programming
    Replies: 16
    Last Post: 03-22-2006, 02:06 AM
  4. Defining main function!
    By alvifarooq in forum C++ Programming
    Replies: 8
    Last Post: 09-19-2004, 02:00 PM