开发者

struct method linking

I'm updating some old code that has several POD structs that were getting zero'd out by memset (don't blame me...I didn't write this part). Part of the update changed some of them to classes that use private internal pointers that are now getting wiped out by the memset.

So I added a [non-virtual] reset() method to the various structs and refactored the code to call that instead.

One particular struct developed an "undefined reference to `blah::reset()'" error.

Changing it from a struct to a class fixed the error.

Calling nm on the .o file h, the mangled function names for that method look the same (whether it's a class or a struct).

I'm using g++ 4.4.1, on Ubuntu.

I hate the thought that this might be a compiler/linker bug, but I'm not sure what else it could be. Am I missing some fundamental difference between structs and classes? I thought the only meaningful ones were the public/private defaults and the way开发者_JS百科 everyone thinks about them.

Update: It actually depends on the way the it's declared:

typedef struct
{
  ...
  void reset();
} foo;

won't link.

struct foo
{
  ...
  void reset();
};

links fine.

So, maybe just a lack of understanding on my part about the way typedefs work in this context?


I think that your problem (and I don't have a standards quote to back this up) is that because your struct doesn't have a name, your member function also does not have a globally identifiable name.

Although you're allowed to use a typedef name to introduce a member function definition, that member function must be part of a named type if you are going to be able to link it to a definition in a different TU.

typedef struct S_ { void reset(); } S;

void S::reset() // OK, but the function actually has id: S_::reset()
{
    // ...
}

typedef struct { void reset(); } T;

void T::reset() // OK, defintion of anonymous struct's reset(),
                // but this isn't an id that can cross TUs.
{
    // ...
}

Edit: This could be a gcc bug, though.

7.1.3 [dcl.typedef] If the typedef declaration defines and unnamed class (...), the first typedef-name declared by the declaration to be that class type (...) is used to denote the class type (...) for linkage purposes only (3.5).

Edit:

Or gcc might be right. While the class has external linkage via its typedef name (3.5/4), a member function has external linkage only if the name of the class has external linkage. Although the class has external linkage and it has a name for linkage purposes only it is still an unnamed class, so it's member functions have no linkage.


Of course, the second declaration is the "proper" C++ way of doing things. Still, this links for me with g++ 4.4.1:

typedef struct {
    void f() {}
} S;


int main() {
    S s;
    s.f();
}

I must confess that the whole struct namespace thing has always been one of the darker corners of C for me, but I'm sure someone else will come up with an explanation.

Edit: OK, minimalist code that reproduces the problem:

// str.h
typedef struct {
    void f();
} S;

// str.cpp
#include "str.h"     
void S :: f() {
}

// sm.cpp
#include "str.h"    
int main() {
    S s;
    s.f();
}

Compiled with:

g++ sm.cpp str.cpp

Error:

undefined reference to S::f()

Now if someone can give us chapter and verse from the standard on why this doesn't work - obviously a struct namespace issue, I would have thought.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜