5

Is there a way to find out the address of main() in C or C++ ? Since it is itself a function ,would there be an address of it own ?

ArtStyle
  • 69
  • 1
  • 3
  • 4
    The main function is considered special in that it has a variety of limitations. One of them is that its address cannot be taken. http://en.cppreference.com/w/cpp/language/main_function has more detail. – qeadz Feb 17 '15 at 17:54
  • 3
    *"Is there a way to find out the address of main() in C/C++ ?"* The phrase "in C/C++" is usually meaningless; ask about C, or C++. They've diverged wildly. – T.J. Crowder Feb 17 '15 at 17:56
  • Why do you ask? On which operating system? With which compiler? – Basile Starynkevitch Feb 17 '15 at 18:08
  • You can have the compiler print out a *map* file which will show the addresses of all the functions. – Thomas Matthews Feb 17 '15 at 18:50
  • Which compiler? Which platform? Some compilers have functions you can call to get addresses of functions. On some compilers, there is a command file that provides the starting address of the `main` function (such as with embedded systems). – Thomas Matthews Feb 17 '15 at 18:51

3 Answers3

18

C

Sure. Simply go ahead and do it.

#include <stdio.h>

int main(void)
{
   printf("%p\n", &main);
}

C++

It is not permitted to take main's address so, for your purposes, there isn't one:

[C++11: 3.6.1/3]: The function main shall not be used within a program. [..]

However, in GCC you can take the same approach as you would in C, via a compiler extension:

#include <iostream>

int main()
{
   std::cout << (void*)&main << '\n';
}

You will receive a warning that this is not compliant.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    The question is wrongly tagged as both C and C++. This answer is correct for C++, but incorrect for C. –  Feb 17 '15 at 17:56
  • _"It is not permitted to take main's address so, for all intents and purposes"_ Not even for printing it out? – πάντα ῥεῖ Feb 17 '15 at 17:58
  • 7
    Unfortunately, that example in C has undefined behaviour. `%p` takes `void *`, not `int (*)(void)`. There's no portable way of printing a function pointer, there's no portable way of converting between object and function pointers. –  Feb 17 '15 at 17:59
  • So ,are you trying to say C++'s main() function can return its address to the user but C can't !! – ArtStyle Feb 17 '15 at 17:59
  • @user3619236: C++'s main() function does not "return its address to the user". – Lightness Races in Orbit Feb 17 '15 at 18:00
  • @LightnessRacesinOrbit I don't think the question is worth answering. But if you are going to answer it anyway, you might as well do it right. :) –  Feb 17 '15 at 18:02
  • 1
    @hvd: There is a way to portable print the address of a function: http://stackoverflow.com/a/10933437/694576 – alk Feb 17 '15 at 18:04
  • @alk What that prints isn't the address of a function, but the representation of an address of a function. Which, admittedly, for practical purposes, is just as good, so I should've mentioned that. Thanks. –  Feb 17 '15 at 18:05
  • @alk: Good point -- but the code in that answer (which breaks down the address into bytes and prints it using `printf("%.2x", ...)`) can in principle produce ambiguous output if `CHAR_BIT > 8`. The `2` implicitly assumes 2 4-bit values per byte; it will print the entire byte value, but if the value exceeds `0xff` it can be impossible to tell where one byte ends and another begins. In practice, this is almost never an issue. – Keith Thompson Feb 17 '15 at 18:07
  • ISO C does allow `void *p; *(int (**)(void)(&p) = main;`. If `sizeof (void *) == sizeof (int (*)(void))`, this and the inverse work: it is the *storage* *representation* that is copied. This is the workaround POSIX.1-2003 and POSIX.1-2008 folks proposed, for example for the inverse cases such as [`dlsym()`](http://man7.org/linux/man-pages/man3/dlsym.3.html). Casting void pointers to function pointers is an optional extension in C99 and C11, and POSIX.1-2013 requires that conforming implementations support that extension. – Nominal Animal Feb 17 '15 at 18:48
  • @NominalAnimal ISO C doesn't allow that, it's a violation of the aliasing rules and at least some versions of GCC will optimise based on the assumption that you don't write code like that. POSIX does add guarantees beyond what C allows, but are you sure this particular form is covered by one of those guarantees? (Note: examples aren't normative. I'm aware of the example in the description of `dlsym`.) I think only `p = (void *) main;` is covered by it. See 2.12.3 Pointer types. –  Feb 17 '15 at 19:05
  • @hvd: I don't see how aliasing rules would be broken by `*(int (**)(void))(&p) = main;`. If a C99/C11/later compiler treats the two expressions differently, I claim the compiler is buggy. I don't know of any GCC version (or flag or optimization) that would make GCC do that. Care to prove me wrong? (POSIX.1-2013 requires the compiler to support `void *p = main;`. Earlier, it was just a suggested workaround. Like I said, I claim ISO C99/C11 does allow the expression, so no reason to rely on POSIX; they just recommended the expression as a workaround.) – Nominal Animal Feb 17 '15 at 19:53
  • @NominalAnimal I referred to 2.12.3 Pointer types, and that explicitly mentions such conversions must be supported "using an explicit cast" (those are the exact words). An implicit conversion is an error just as it always was. As for `*(int (**)(void))(&p) = main;`, it's a violation of the aliasing rules, C99 6.5p7, that describe in which circumstances an object may be accessed by an incompatible type. That doesn't allow a distinct pointer type, and neither does POSIX. GCC 4.5 warns (`-O2 -Wall`): "warning: dereferencing type-punned pointer will break strict-aliasing rules". –  Feb 17 '15 at 20:00
  • 1
    @NominalAnimal And it's easy to come up with an example where it breaks: [this example](http://ideone.com/1SlVmq) returns zero with later GCC versions, but one with GCC 4.5. If you think that's a conformance issue that got fixed in later versions, I'd be happy to read whatever standard it failed to conform to, but as far as I can tell, returning 1 is perfectly valid in all versions of C and all versions of POSIX. –  Feb 17 '15 at 20:05
  • @hvd: Using GCC 4.4.7, the example returns zero, although GCC claims your example breaks strict-aliasing rules (probably bug 41874). GCC 4.6.4 and later do not complain, but return zero too. It is GCC 4.5 that behaves differently to versions prior or after (and a version I have skipped myself). Anyway, if one were to agree with you, the workaround is to use `void *p; int (*f)(void) = main; memcpy(&p, &f, sizeof f);`. – Nominal Animal Feb 17 '15 at 21:19
  • @NominalAnimal GCC 4.4.7 returns one too, if optimisations are enabled (`-O2`, like I mentioned I used with GCC 4.5). So do 4.3.6, 4.2.4, 4.1.2, 4.0.4, 3.4.6 and 3.3.6. It's not like 4.5 suddenly changed this. It doesn't look like the bug you refer to: there really is an aliasing problem in my sample program. You're right that `memcpy` is a valid workaround: that too isn't supported by ISO C (since it doesn't require the same representations for different pointer types, and even allows `sizeof p != sizeof f`), but it's guaranteed by POSIX. –  Feb 17 '15 at 21:26
  • @hvd: GCC 4.4.7 returns zero with `-O1` or `-O2 -fno-strict-aliasing`. Personally, I rely on the compiler to handle `void *p; p = main;` (C99/C11 optional extension J.5.7, also POSIX.1-2013), `void *p; *(int (**)(void))(&p) = main;`, and `void *p; { int (*f)(void) = main; memcpy(&p, &f, sizeof f);` the exact same way. Even if I am wrong about ISO C99/C11 compliance, all three **must** produce the same `p` (or not compile), or a buttload of C code (including code written to POSIX.1-2003/-2008 suggestions) will miscompile. One of these must work for polymorphic function pointers (e.g. dlsym()). – Nominal Animal Feb 17 '15 at 21:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/71116/discussion-between-hvd-and-nominal-animal). –  Feb 17 '15 at 21:58
  • @Lightness Races in Orbit: your C example is not quite correct: in C, the name of a function is a pointer to the function, so you should use main instead of &main in the printf call. – Jeff Buck Feb 19 '15 at 23:37
  • My previous comment was not quite correct-- using g++, both main and @main give the same result. – Jeff Buck Feb 19 '15 at 23:50
  • @JeffBuck: `g++` compiles C++, not C (although if your file extension is `.c` then you'll still get away with it). Anyway, `&main` is the same as `main` in this context, but better expresses intent. As always, I tested and verified both snippets before posting this answer. – Lightness Races in Orbit Feb 20 '15 at 00:58
4

I wasn't 100% sure whether the question was meant from within a program using C/++ or to retrieve address of the main() function created with C/C++ (meaning from the command line).

Since it looks like you've received several good answers on how to get the address from within the program, I thought I'd mention you can get this info from nm as well.

nm program|grep main
user590028
  • 11,364
  • 3
  • 40
  • 57
1

If for any system you can't find the address of main.. put an invocation to a function foo() as the only statement in main, have main return whatever it returns and use the address of foo rather than main.

Note that calling main won't necessarily restart your code, even if there are no static/global variables. The compiler generates start up code before actually calling main.

If you want to breakpoint before this call to main write something like:

static int i=foo();

and foo will be called during the earlier data initialisation step.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Ian Davis
  • 21
  • 2