4

Before the actual implementation, i wrote a small prototype code, and put a class constructor and ctor constructor in the same file, to see if the ctor would execute first, which is my actual implementation.

However, i am facing an error. Here is the code:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <iostream>

using namespace std;

extern "C" void startMe(void) __attribute__ ((constructor(1)));
extern "C" void ending(void) __attribute__ ((destructor));

class Test {

 public:

    Test()
    {
      cout << "This is test constructor" << endl;
    }
 };

 int main()
 {
  Test();
  printf("Now main called\n");
 }

 void startMe(void)
 {
  printf("Start me called before main\n");
 }

 void ending(void)
 {
  printf("Destructor called\n");
 }

--

Output:
 $ g++ constructor1.cc 
 constructor1.cc:10: error: wrong number of arguments specified for ‘constructor’ attribute

However, when i remove the constructor priority, it compiles and runs fine. That is, i do:

extern "C" void startMe(void) __attribute__ ((constructor)); 

Why is it so? How to give priority?

Please help me. My idea is "ctor" should be executed first, then the other (Test) constructor. The same reason, i have put ctor as a priority 1.

jww
  • 97,681
  • 90
  • 411
  • 885
RajSanpui
  • 11,556
  • 32
  • 79
  • 146
  • 1
    C has no constructors or destructors. Tag removed. – pmg Jul 05 '11 at 10:07
  • It has, that is what is ctor. The tag should not be removed. I have rolled it back. – RajSanpui Jul 05 '11 at 10:08
  • You can add a constructor to a C code..search my earlier posts..FYI. – RajSanpui Jul 05 '11 at 10:09
  • @kingsmasher: "ctor" is the abbrevation of "constructor" and there is no such thing in C, tag removed. – Xeo Jul 05 '11 at 10:09
  • 2
    @kingsmasher1: it also doesn't have `extern "C"` or classes or `` or `using` or `namespace` or `cout` or (**very**) strange usage of the operator `<<`, or ... , ... , .... – pmg Jul 05 '11 at 10:10
  • That is different, my idea is, my file can be linked with C and C++ code. This is a snippet. __attribute__((constructor)) allows constructors in C language..i think we are swaying away from the actual discussion. – RajSanpui Jul 05 '11 at 10:12
  • 1
    http://stackoverflow.com/questions/2053029/how-exactly-does-attribute-constructor-work – Cheers and hth. - Alf Jul 05 '11 at 10:13
  • Maybe you want to tag your question with `gcc` ... and untag `c`, `c++`, `g++` :) – pmg Jul 05 '11 at 10:20
  • 1
    The real question is are you compiling the code as C or as C++? Please choose tags that accurately reflect the question, not just those that are closely associated in your mind. – Cody Gray - on strike Jul 05 '11 at 10:25
  • Both. This question won't make sense for C++ and non-Linux folks because they won't get the ctor concept. This code is actually a snippet of a library, that can be linked with C as well as C++. I am testing with both "as in" C and as in "C++". So many people i repeated the same answer i guess :( – RajSanpui Jul 05 '11 at 10:29
  • I do not believe you that you compile this code with a C compiler, as C has no notion of `class`es. – Xeo Jul 05 '11 at 10:35
  • 2
    I've removed the C tag again. The fact that this can be linked into a C program is completely tangential to the actual question. – Oliver Charlesworth Jul 05 '11 at 10:36
  • @kingsmasher1 It doesn't matter that that the final product is a library that can be used by C++ programs. Plenty of languages can interface with C and produce a library that can be linked to a C program. It doesn't make sense to use the C tag for those or this question either. Nor does it matter that you are using a GCC extension. – Luc Danton Jul 05 '11 at 10:37
  • You're right, I'm not a Linux folks. But I'm still really curious to know what C compiler you're using that understands the keyword `class`. I asked what you're compiling **this** code as, C or C++, not what language you eventually want to try and call it from. You could be calling it from C# or VB or Lua too. I can't see how that's relevant to the question itself. – Cody Gray - on strike Jul 05 '11 at 10:38
  • @Luc: I agree about C, but AFAICS, the question is specifically about the interaction between the GCC extension and C++, so I think the GCC tag is relevant. – Oliver Charlesworth Jul 05 '11 at 10:38
  • @Oli It is. I was mentioning that in relation to the C tag. – Luc Danton Jul 05 '11 at 10:43

2 Answers2

1

Compiling your program as is yields:

warning: constructor priorities from 0 to 100 are reserved for the implementation

Changing the priority from 1 to 101 gets rid of the warning and the executable produces:

 Start me called before main
 This is test constructor
 Now main called
 Destructor called

This is using GCC 4.5

Luc Danton
  • 34,649
  • 6
  • 70
  • 114
  • constructor1.cc:10: error: wrong number of arguments specified for ‘constructor’ attribute – RajSanpui Jul 05 '11 at 10:50
  • @kingsmasher1 This is using GCC. Both gcc and g++ do the same thing here. – Luc Danton Jul 05 '11 at 10:52
  • Although, it executes fine in my ARM target, but in x86 it fails. – RajSanpui Jul 05 '11 at 10:53
  • No, you can't compile it using gcc, u have to use g++ compiler here – RajSanpui Jul 05 '11 at 10:53
  • @kingsmasher1 `gcc -lstdc++` can work just fine, not that it's relevant to what's at hand. – Luc Danton Jul 05 '11 at 10:55
  • You are linking the C++ library using, -lstdc++. Why will you do that, when you can directly invoke g++? I don't feel it is appropriate way to do (Linking C++ library using C compiler). I feel we are diverting from the actual point. Pls help to clarify the actual question if u can. – RajSanpui Jul 05 '11 at 11:00
  • @kingsmasher1 For starters you could provide your GCC version. For all we know the priority feature isn't supported for your version. – Luc Danton Jul 05 '11 at 11:03
  • Yes, i think, that is the problem: my CentOS GCC version in x86 has 4.1. – RajSanpui Jul 05 '11 at 11:09
  • @kingsmasher1 FWIW the [manual](http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Function-Attributes.html#Function-Attributes) for 4.1 doesn't document the priority syntax for constructor attributes. – Luc Danton Jul 05 '11 at 11:13
  • Luc, thank you. I think that is the root cause. But then how to make sure that my __attribute__ constructor has highest priority if priority can't be set? – RajSanpui Jul 05 '11 at 11:19
  • @kingsmasher1 I suggest opening a new question for that – Luc Danton Jul 05 '11 at 11:30
0

wrong number of arguments specified for ‘constructor’ attribute

It looks like you are using a downlevel version of GCC.

According to the GCC 4.2.1 docs, the following are the relevant GCC 4.2.1 Function Attributes:

constructor
destructor
    The constructor attribute causes the function to be called automatically before execution enters main ()...

And the relevant GCC 4.3.0 Function Attributes:

constructor
destructor
constructor (priority)
destructor (priority)
    The constructor attribute causes the function to be called automatically before execution enters main ()...

The solution is to use GCC 4.3 or above.

I'm currently testing some software on OpenBSD 5.7, and it ships with the GCC 4.2.1 compiler. We also support CentOS 5, and that ships with the GCC 4.1 compiler. Here's what out code looks like:

// INIT_PRIORITY manages initialization of C++ static objects. Under GCC, 
// the library uses init_priority attribute in the range [INIT_PRIORITY,
// INIT_PRIORITY+100]. Under Windows, INIT_PRIORITY enlists
// "#pragma init_seg(lib)". Undefine or set to 0 to disable it.
#define INIT_PRIORITY 250

#ifdef __GNUC__
# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
#ifdef __clang__
# define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#endif
...

#if __GNUC__ && INIT_PRIORITY && ((GCC_VERSION >= 40300) || (CLANG_VERSION >= 20900))
DLL void API DetectX86Features() __attribute__ ((constructor (INIT_PRIORITY + 50)));
DLL bool API CpuId(word32 input, word32 *output);
#elif __GNUC__ && INIT_PRIORITY
DLL void API DetectX86Features() __attribute__ ((constructor));
DLL bool API CpuId(word32 input, word32 *output);
#else
DLL void API DetectX86Features();
DLL bool API CpuId(word32 input, word32 *output);
#endif

You should probably create an additional class, like Initialization, and put startMe in the constructor and ending in the destructor. Then, create a static instance of the C++ object, like Initialization init;.

To avoid the static initialization order fiasco, you should use init_priority (also see this Stack Overflow question and Clarification of attribute init_priority on the GCC mailing list). init_priority has been around since at least GCC 3.2.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885