Re: LNK1179: duplicate COMDAT (templates, vc2003)

Jon Watte <[email protected]> Thu, 22 Mar 2007 17:08:09 -0700
Newsgroups gmane.games.devel.windows
Message-ID <[email protected]>
And the ACTUAL error, for those of who you need such things, is:

media fatal error LNK1179: invalid or corrupt file: duplicate COMDAT 
'?Access@?$FieldArrayAccessor@USasCamera@impl_DX9@@M$GIA@A@A@@impl_DX9@@QAEPBMABUSasCamera@2@@Z'


Cheers,

          / h+


Jon Watte wrote:
> We're using VC 2003 (can't upgrade to 2005 just yet, although it's on 
> the long-term map).
>
> When building a certain file, which uses some moderately simple 
> templates, I get a linker error about duplicate COMDAT sections for a 
> specific template instantiation. It seems as if the function in question 
> is being instantiated twice in the same obj file by the compiler.
>
> Googling for this turns up a bunch of errors in VC6, which have nothing 
> to do with this problem, and a few people who had problems with some bg 
> in the incremental linker. I've turned off incremental linking for this 
> library (I'm building a DLL), and the error still happens.
>
>
> I'm looking for the following things:
>
> 1) A fix for a known problem.
> 2) Suggestions for how to work around this problem.
> 3) A drinking buddy who has the same problem and can relate to the sorrow.
>
>
> The code looks somewhat like:
>
> namespace impl_DX9 {
>
> template<typename Container, typename Type, Type (Container::*Field)[]>
> class FieldArrayAccessor {
>   public:
>     typedef Container ContainerType;
>     typedef Type FieldType;
>     Type const *Access(Container const &c) { return c.*Field; }
> };
>
> //  Match SasCamera
> struct SasCamera {
>   Mat4Float        worldtoview;    //  will always be the identity transform
>   Mat4Float        projection;
>   float            nearfarclipping[2];
>   FastTriple       position;       //  because the camera is always the 
> center of the world view, it's always 0,0,0
> };
>
>
> I have tried making the Access() functions be inline static, and regular 
> static as well (in fact, they started life out being inline static); I 
> still get this error.
>
> The three uses of the template in the file look like this:
>
>
>   return new WholeArraySetter<FieldArrayAccessor<
>       SasCamera, float, reinterpret_cast<float 
> (SasCamera::*)[]>(&SasCamera::nearfarclipping)>
>       >(pb, cam, 2);
>
>       setter_ = new ArrayItemSetter<FieldArrayAccessor<
>           SasCamera, float, reinterpret_cast<float 
> (SasCamera::*)[]>(&SasCamera::nearfarclipping)>
>           > (this, core_->camera_, l);
>
>   setter_ = new WholeArraySetter<FieldArrayAccessor<
>       SasSkeleton, pit::Mat4Float, reinterpret_cast<pit::Mat4Float 
> (SasSkeleton::*)[]>(
>       &SasSkeleton::meshtojointtoworld)> >(this, core_->skeleton_, 
> &core_->skeleton_.get().numjoints);
>
>
> The templates that invoke the actual instance (Access function) look 
> like (look at the Update() functions):
>
> template<typename Accessor>
> class WholeArraySetter : public IValueSetter {
>   public:
>     //  When the count is fixed, stuff it in a member, and point the 
> pointer at that.
>     WholeArraySetter(ParameterBinder *bind, DirtyState<typename 
> Accessor::ContainerType> const &ds, int cnt)
>         : bind_(bind), ds_(ds), cnt_(cnt) { cntptr_ = &cnt_; }
>     //  When the count is variable, bind using a pointer. The 'cnt' is 
> not used.
>     WholeArraySetter(ParameterBinder *bind, DirtyState<typename 
> Accessor::ContainerType> const &ds, int const *cnt)
>         : bind_(bind), ds_(ds), cntptr_(cnt) { cnt_ = -1; }
>     virtual void Dispose() { delete this; }
>
>     virtual HRESULT Update(ID3DXEffect *fx) {
>       if (!ds_.dirty()) {
>         return S_OK;
>       }
>       //later: handle type casting (float->int, etc).
>       return fx->SetValue(bind_->param_, Accessor().Access(ds_.get()),
>           sizeof(typename Accessor::FieldType) * *cntptr_);
>     }
>
>     ParameterBinder *bind_;
>     DirtyState<typename Accessor::ContainerType> const &ds_;
>     int cnt_;
>     int const *cntptr_;
> };
>
> template<typename Accessor>
> class ArrayItemSetter : public IValueSetter {
>   public:
>     //  When the count is fixed, stuff it in a member, and point the 
> pointer at that.
>     ArrayItemSetter(ParameterBinder *bind, DirtyState<typename 
> Accessor::ContainerType> const &ds, int cnt)
>         : bind_(bind), ds_(ds), cnt_(cnt) {}
>     virtual void Dispose() { delete this; }
>
>     virtual HRESULT Update(ID3DXEffect *fx) {
>       if (!ds_.dirty()) {
>         return S_OK;
>       }
>       //later: handle type casting (float->int, etc).
>       return fx->SetValue(bind_->param_, Accessor().Access(ds_.get()) + 
> cnt_,
>           sizeof(typename Accessor::FieldType));
>     }
>
>     ParameterBinder *bind_;
>     DirtyState<typename Accessor::ContainerType> const &ds_;
>     int cnt_;
> };
>
>
>
> -------------------------------------------------------------------------
> Take Surveys. Earn Cash. Influence the Future of IT
> Join SourceForge.net's Techsay panel and you'll get the chance to share your
> opinions on IT & business topics through brief surveys-and earn cash
> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
> _______________________________________________
> Gamedevlists-windows mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/gamedevlists-windows
> Archives:
> http://sourceforge.net/mailarchive/forum.php?forum_id=555
>
>
>   

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Gamedevlists-windows mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gamedevlists-windows
Archives:
http://sourceforge.net/mailarchive/forum.php?forum_id=555