This bugzilla service is closed. All entries have been migrated to https://gitlab.com/libeigen/eigen

Bug 83

Summary: [MSVC] Compilation error in Visual Studio 2008
Product: Eigen Reporter: isluser <miralles.francois>
Component: InteroperabilityAssignee: Nobody <eigen.nobody>
Status: RESOLVED WONTFIX    
Severity: Unknown CC: fmdspam, gael.guennebaud, hamelin.philippe, hauke.heibel, jacob.benoit.1, jitseniesen, joseluisblancoc, mathieu.gautier, pdanilewski, thomas.retornaz
Priority: ---    
Version: 3.0   
Hardware: x86 - 32-bit   
OS: Windows   
Whiteboard:
Bug Depends on:    
Bug Blocks: 387    
Attachments:
Description Flags
test case
none
MSVC Deque v1.1
none
build log none

Description isluser 2010-10-19 22:45:06 UTC
The following error happens when compiling in Visual Studio 2008

c:\Program Files\Microsoft Visual Studio 9.0\VC\include\deque(715): error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
Comment 1 Benoit Jacob 2010-10-20 00:27:25 UTC
When compiling what?

Can you please provide a test case or steps to reproduce?
Comment 2 Benoit Jacob 2010-10-20 04:05:12 UTC
Should be fixed now. Feel free to reopen if not.
Comment 3 Benoit Jacob 2010-10-20 04:06:01 UTC
argh, closed the wrong bug.
Comment 4 isluser 2010-10-20 15:39:39 UTC
That's when I compile the EigenTesting solution.
Comment 5 Jose Luis Blanco 2010-11-09 23:37:02 UTC
Created attachment 32 [details]
test case
Comment 6 Jose Luis Blanco 2010-11-09 23:40:01 UTC
I confirm the issue is still there: I attach test case with std::vector that works and std::deque that fails with:

1>d:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\deque(715) : error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned

1>        eigen\src/StlSupport/StdDeque.h(98) : see reference to class template instantiation 'std::deque<_Ty,_Ax>' being compiled

It seems MSVC is trying to instantiate the correct specialization for the aligned allocator, but still try to use the base std::deque resize() method and fails. 

I hope you guys know how to fix this!
Comment 7 Benoit Jacob 2010-11-10 09:31:22 UTC
Hauke is the VC specialist here :-)

also moving to 'interoperability' since this is about STL support
Comment 8 Hauke Heibel 2010-11-20 13:31:23 UTC
I just wanted to note that we need a VC9 (MSVC 2008) volunteer to fix this issue. I moved on to VC10 (MSVC 2010) and cannot reproduce the issue over here.
Comment 9 Jose Luis Blanco 2010-11-20 13:54:21 UTC
(In reply to comment #8)
> I just wanted to note that we need a VC9 (MSVC 2008) volunteer to fix this
> issue. I moved on to VC10 (MSVC 2010) and cannot reproduce the issue over here.

Send me your patches and I'll test them (joseluisblancoc at gmail dot com).
Comment 10 Hauke Heibel 2010-11-20 14:06:00 UTC
I have no clue how to patch since it is working properly over here. :)

To get some clues, could you please test the following by running your test program in 32bit mode with SSE2 enabled?

a) Expand the resize implementation in StdDeque.h (line 104) and check via a break-point whether the code is reached.

b) Add another break-point in line 110 on "if (deque_base::size() < new_size)" and check whether this code is reached.

c) Verfiy that _Insert_n of the std::deque has the following signature (the reference on _Val is important)

void _Insert_n(const_iterator _Where,
		size_type _Count, const _Ty& _Val)

In case b) fails, please check in the <deque> header if the include guards are based on _DEQUE_.

Having this information we are a step closer to a solution.

On VC10, a) as well as b) are reached. The signature of _Insert_n is corresponding to what I've written under c) and the <deque> header is guarded via _DEQUE_.
Comment 11 Gael Guennebaud 2011-02-04 22:25:07 UTC
There have been many fixes recently, so is it still valid?
Comment 12 Benoit Jacob 2011-02-07 17:04:09 UTC
Ping. Does this bug still exist?
Comment 13 Hauke Heibel 2011-02-07 17:10:19 UTC
Pong. Yes.

http://eigen.tuxfamily.org/CDash/viewBuildError.php?buildid=4778
Comment 14 Jose Luis Blanco 2011-02-07 17:15:21 UTC
I'll give a try to Hauke's ideas in comment #10 tonight (West-Europe timezone!) and let you know...
Comment 15 Hauke Heibel 2011-02-07 17:55:52 UTC
*** Bug 181 has been marked as a duplicate of this bug. ***
Comment 16 Jose Luis Blanco 2011-02-08 00:19:34 UTC
Well, I got back on this but it really defies me...

Hauke: The problem appears at build time, so I'm unable to do any tracing, sorry!

The complete error I have for:

 deque<MyStruct, Eigen::aligned_allocator<MyStruct> > vec2;

(note that there's no explicit call to resize()), is:


1>d:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\deque(715) : error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
1>        d:\code\eigen-hg\eigen\src/StlSupport/StdDeque.h(98) : see reference to class template instantiation 'std::deque<_Ty,_Ax>' being compiled
1>        with
1>        [
1>            _Ty=Eigen::internal::workaround_msvc_stl_support<MyStruct>,
1>            _Ax=Eigen::aligned_allocator_indirection<Eigen::internal::workaround_msvc_stl_support<MyStruct>>
1>        ]
1>        ..\..\test\adjoint.cpp(22) : see reference to class template instantiation 'std::deque<_Ty,_Ax>' being compiled
1>        with
1>        [
1>            _Ty=MyStruct,
1>            _Ax=Eigen::aligned_allocator<MyStruct>
1>        ]


Just in case, I tried replacing T in EIGEN_STD_DEQUE_SPECIALIZATION_BODY by EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T) without luck. 

The code in the STL support files is probably as clear as it could be, but please correct me if I don't get something right (hopefuly in the process we could deduce WTF is going on here):

- This is a specialization of std::deque, right?

  template<typename T>
  class deque<T,EIGEN_ALIGNED_ALLOCATOR<T> >
    : public deque<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T), Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> >


- It happens after #include <deque>. I'm sure because I added an 

#if !defined(_DEQUE_)
#error foo
#endif

and it didn't occur.

- The deque_base class seems to me to be the correct one:

typedef deque<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> > deque_base;

which in my example expands to:

1>        d:\code\eigen-hg\eigen\src/StlSupport/StdDeque.h(98) : see reference to class template instantiation 'std::deque<_Ty,_Ax>' being compiled
1>        with
1>        [
1>            _Ty=Eigen::internal::workaround_msvc_stl_support<MyStruct>,
1>            _Ax=Eigen::aligned_allocator_indirection<Eigen::internal::workaround_msvc_stl_support<MyStruct>>
1>        ]


- so, the key: Why on earth does MSVC complains on original deque's:

void resize(size_type _Newsize, _Ty _Val) {} 

if "ours": 

void resize(size_type new_size)

in the derived class should HIDE all base class methods named "resize()"???

I wasn't able to find any fundamental difference with the case of the std::vector, but still, there must be something I overlooked...

Any ideas??
Comment 17 Hauke Heibel 2011-02-08 07:47:39 UTC
Ok, we probably need some more iterations. I tried to simplify the code a bit and removed the EIGEN_STD_DEQUE_SPECIALIZATION_BODY macro. It was just used once.

Furthermore, I added a bunch of 'pragma message("...")' in order to get some compile time traces from MSVC.

Since I did not comment it in the beginning, quickly the explanation for the aligned_allocator_indirection. I added the following comment of which I hope that it helps:

// This redundant class is needed to prevent reimplementing the whole std::vector.
//
// To be precise, we added this class in order to prevent a recursive specialization
// of std::vector< T, EIGEN_ALIGNED_ALLOCATOR<T> >.
// To spare us from reimplementing everything we, std::vector< T, EIGEN_ALIGNED_ALLOCATOR<T> >
// should be its own base class which is only possible with this indirection.

A test version of StdDeque.h is now attached. It shouldn't change anything but be a bit more verbose on its outputs. Its for MSVC only!
Comment 18 Hauke Heibel 2011-02-08 07:48:30 UTC
Created attachment 87 [details]
MSVC Deque v1.1
Comment 19 Jose Luis Blanco 2011-02-08 09:03:16 UTC
Thanks Hauke. 
As expected, it only shows the "good path" message, although it appears twice. 
I attach the output log "build_out_1.txt", also with /showIncludes enabled.
Comment 20 Jose Luis Blanco 2011-02-08 09:03:50 UTC
Created attachment 88 [details]
build log
Comment 21 Benoit Jacob 2011-02-08 15:24:16 UTC
No need to block beta3, only 3.0-final.
Comment 22 Hauke Heibel 2011-02-09 13:47:35 UTC
I've had a chance to look at the issue in VS2008.

The problem is that for some strange reason visual studio performs a full instantiation of 

std::deque< Matrix2f, aligned_allocator<Matrix2f> >

including the compilation of

resize(size_t new_size, Matrix2f val)

which ultimately triggers the error.

To be even more precise, it is our workaround_msvc_stl_support which fails to work for deque. As soon as we stop deriving from "public T" it compiles though we obviously need to derive from T.

No clue at all how to solve this! Not even a remote idea why this is happening for std::deque and not for std::vector. I am also confused that

std::vector<Matrix2f> m; m.resize(20, Matrix2f());

compiles ... it crashes of course at run-time, but why does it compile!?

- Hauke
Comment 23 Mathieu Gautier 2011-02-15 15:13:04 UTC
Hi, I was able to take a closer look. I have good and bad news.

The (almost) good one. I think I have a small test case which show the bug :

first a small (non standard) container (container.h):

#pragma once

// reproduce deque crash (maybe caused by the used of sizeof line 517/518 by _DEQUESIZ macro)

template<typename T>
class container {
  // declaring CRASH variable force an explicit instantiation of resize (even in other stl containers)
  // comment out the following variable to build
  static const int CRASH = sizeof(T);
public:
  container(const T& _Val) {}

  void resize(T Val) {}
};

// Eigen work around for MSVC

#include <Eigen/Eigen>
#include "Eigen/src/StlSupport/details.h"

template<typename T>
class container2 : public container<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)>{
public:
  container2(const T& _Val) : container(_Val) {}

  void resize(const T& Val) {}
};

and the main :

#include "container.h"
#include <Eigen/Core>
#include <Eigen/StdVector>

int main() {
  container2<Eigen::Matrix2f> c(Eigen::Matrix2f::Random(2,2));
  return 0;
}

The explicit instantiation of container::resize(T) is forced by the static const int in container. (There is a similar call to sizeof in deque).

The bad news is that the following code will make the std::vector fail, even if container::resize(T) is commented out in container<T> :

#include "container.h"
#include <Eigen/Core>
#include <Eigen/StdVector>

int main() {
  container2<Eigen::Matrix2f> c(Eigen::Matrix2f::Random(2,2));

  // using std::vector will also fail to build, unless sizeof(T) is commented out in container2
  std::vector<Eigen::Matrix2f ,Eigen::aligned_allocator<Eigen::Matrix2f> > w(20, Eigen::Matrix2f::Random(2,2));

  return 0;
}

That is to say, using std::deque before std::vector will also make std::vector fail. It build fine if vector is called first and container::resize(T) is not declared. 

I don't understand how container can affect std:vector specialization, MSVC magic.

-- 
Mathieu Gautier
Comment 24 Mathieu Gautier 2011-02-15 18:05:51 UTC
In fact, it can be futher track down to the work_around :

#include <Eigen/Core>
#include <Eigen/StdVector>

int main() {
  sizeof(Eigen::internal::workaround_msvc_stl_support<Eigen::Matrix2f>);

  // using std::vector will fail unless the previous sizeof is commented out.
  std::vector<Eigen::Matrix2f ,Eigen::aligned_allocator<Eigen::Matrix2f> > w(20, Eigen::Matrix2f::Random(2,2));

  return 0;
}
Comment 25 Jitse Niesen 2011-03-19 15:18:08 UTC
We discussed it during the Eigen meeting and decided not to block 3.0 on this.
Comment 26 pdanilewski 2011-04-12 07:43:14 UTC
Hi,

I reached this site by accident, googling for this particular error in MSVC.
The "formal parameter with __declspec(align('16'))" error usually occurs when a value which should be aligned (in this case: to 16 bytes) is passed by a value, instead of const-reference.

I just edited the offending line 714 in <deque>:

-	void resize(size_type _Newsize, _Ty _Val)
+	void resize(size_type _Newsize, const _Ty &_Val)


There were lots of those bugs in VC 6.0, I am surprised to see one in 2008 version. 
Unless, of course, there is a good reason why const-reference is inapprioriate, that I am not aware of...

Hope it helps your problem.
Comment 27 Philippe Hamelin 2011-05-19 15:42:59 UTC
I am using Eigen 3.0 on Visual Studio 2008 and I have the exact same problem. Is there currently any workaround?

What are the limitations caused by this bug? Does this only mean that I can't put Eigen types into STL containers?
Comment 28 Gael Guennebaud 2011-05-23 14:44:50 UTC
one workaround is to disable static alignment by defining:

EIGEN_DONT_ALIGN_STATICALLY

before any Eigen header. This way all your alignment issues are gone, just like the vectorization of fixed size objects (e.g., Matrix4f).
Comment 29 Retornaz Thomas 2011-06-06 10:25:20 UTC
Hi 
I add the following lines in CMakeList

if(MSVC90)
  add_definitions(-DEIGEN_DONT_ALIGN_STATICALLY=1)
  message(STATUS "Disabling static for msvc8")
endif(MSVC90)	

It seems a correct work around
All test compils (see2,openmp activated) [1]
It sounds great! 

Nevertheless, what is the impact on this workaround?
Performance regression on small fixed size matrix/vector ?

Thank you all, for your great jobs

Regards 
TR


[1] except few compilations bloat but its not really important
Targeted platform:
Windows Xp64 SP2 Visual 2008 SP1 build x86
Comment 30 Benoit Jacob 2011-06-06 13:36:01 UTC
(In reply to comment #29)

By doing this, you lose vectorization of small fixed-size Eigen objects such as Vector4f, see
http://eigen.tuxfamily.org/dox/TopicFixedSizeVectorizable.html
Comment 31 Benoit Jacob 2011-06-06 13:37:13 UTC
To answer your specific question, yes the effect of this is that you lose performance.
Comment 32 Retornaz Thomas 2011-06-06 13:50:53 UTC
Ok thanks

our goals are to test eigen capability for some machine learning algorithms 
So the matrix/vector involved are not so tiny :)

Visual 2008 is must have for us even if we mostly developp under linux/gcc

Thank for all

Thomas
Comment 33 Gael Guennebaud 2012-03-26 18:15:34 UTC
no obvious solution yet, -> 3.2
Comment 34 Jose Luis Blanco 2013-03-04 22:55:29 UTC
The bug is still there in 3.1.2. 

These are my last tests: 

- MSVC9, MSVC10, MSVC11, in x64 -> Works (the bug doesn't show up)
- MSVC11 x32 -> Works.
- MSVC9, MSVC10, in x32 -> FAILS.

It only affecting 32bit builds makes me suspect it must have something to do with size_t, but (once again) couldn't locate the particular source of the problem...

Cheers,
JL
Comment 35 Jose Luis Blanco 2013-03-04 23:01:11 UTC
PS: Or it may also be that in 64bit builds, memory align is not an issue.
Comment 36 Gael Guennebaud 2013-07-11 23:55:54 UTC
it seems to be fixed in MSVC11, and I don't see what we can do ourself, so let's close it.
Comment 37 Frank Meier-Dörnberg 2013-07-12 07:29:42 UTC
(In reply to comment #36)
> it seems to be fixed in MSVC11, and I don't see what we can do ourself, so
> let's close it.

In contrast to the last test of Jose in Comment 34,
it seems to me not to fail in MSVC10 (vc100sp1-sse2-32bit)
Please see here: http://manao.inria.fr/CDash/viewBuildError.php?buildid=7344

If so, personally consider the bug as closable.

Nevertheless, I perform a test for MSVC9 (vc90sp1-sse2-32bit), let's see.

Cheers
Frank
Comment 38 Frank Meier-Dörnberg 2013-07-13 01:36:43 UTC
I have patched the VC9 deque source as follow:

-void resize(size_type _Newsize, _Ty _Val)
+void resize(size_type _Newsize, _Ty& _Val)

and reperform the full set of tests for MSVC9 (vc90sp1-sse2-32bit).
Tataa! Problem gone. Please see here:
http://manao.inria.fr/CDash/buildSummary.php?buildid=7356

For me, this bug is closed.

Cheers Frank
Comment 39 Gael Guennebaud 2013-07-13 09:06:18 UTC
yes, we cannot do much on our side.
Comment 40 Nobody 2019-12-04 09:48:25 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to gitlab.com's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.com/libeigen/eigen/issues/83.