Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

icpc lambda capture by value + return by value = incorrect code generation

Ryan_Goodfellow
Beginner
670 Views

Using icpc as follows (version 15.0.0 20140530 on Ubuntu 14.04)

icpc -std=c++11 <file> -o <out> -O0

for the following code, yields an executable that segfaults (backtrace following the code, core file attached). This does not occur in g++ or clang++. Yes the lambda does not do anything, but that is not the point, this is a simplification of real code that isolates the problem. There seems to be an issue with the generated code versus the copy semantics for std::shared_ptr.

As an aside, what is the status for using Clang with Xeon Phi cards? We are developing c++11 code to run across x86_64 and MIC and would _much_ rather just use Clang for both.

#include <string>
#include <iostream>
#include <memory>

using namespace std;

struct S
{
  shared_ptr<string> s; 

  S(string *s) : s{s} {}
};

S meh()
{
  S c{new string("meh")};
  auto l = () -> void{ cout << c.s << endl; };
  return c;
}

int main()
{
  S s = meh();

  return EXIT_SUCCESS;
}

#0  0x0000000000400e01 in _INTERNAL_27_lambda_capture_by_value_cxx_7c66d640::__gnu_cxx::__atomic_add_single(int*, int) ()
#1  0x0000000000400e9d in _INTERNAL_27_lambda_capture_by_value_cxx_7c66d640::__gnu_cxx::__atomic_add_dispatch(int*, int) ()
#2  0x0000000000401243 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_add_ref_copy() ()
#3  0x000000000040138b in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count(std::__shared_count<(__gnu_cxx::_Lock_policy)2> const&) ()
#4  0x00000000004014fd in std::__shared_ptr<std::string, (__gnu_cxx::_Lock_policy)2>::__shared_ptr(std::__shared_ptr<std::string, (__gnu_cxx::_Lock_policy)2> const&) ()
#5  0x0000000000401523 in std::__shared_ptr<std::string, (__gnu_cxx::_Lock_policy)2>::__shared_ptr(std::__shared_ptr<std::string, (__gnu_cxx::_Lock_policy)2> const&) ()
#6  0x00000000004016af in std::shared_ptr<std::string>::shared_ptr(std::shared_ptr<std::string> const&) ()
#7  0x00000000004010a7 in S::S(S const&) ()
#8  0x0000000000400f90 in meh() ()
#9  0x0000000000400fe8 in main ()

~ ry

0 Kudos
9 Replies
Om_S_Intel
Employee
670 Views

I did not get the error when in my environment.

 

$ uname -a
Linux dpdknf05 2.6.32-279.el6.x86_64 #1 SMP Wed Jun 13 18:24:36 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux
[opsachan@dpdknf05 Q6000062076]$ gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
$ icc -V
Intel(R) C Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.0.090 Build 20140723
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

$ cat tstcase.cpp
#include <string>
#include <iostream>
#include <memory>
using namespace std;
struct S
{
  shared_ptr <string> s;
  S(string *s) : s{s} {}
};

S meh()
{
   S c{new string("meh")};
   auto l = () -> void{ cout << c.s << endl; };
   return c;
}

int main()
{
   S s = meh();
   return EXIT_SUCCESS;
}

$ icpc -std=c++11 tstcase.cpp -o tstcase -O0
$ ./tstcase

0 Kudos
Ryan_G_
Beginner
670 Views

you also seem to be running a newer version of icc than I am. Is this version available in the beta program yet?

~ry

 

[ry@localhost ~]$ uname -a
Linux localhost.localdomain 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
[ry@localhost ~]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.2/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.2-20140120/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.2-20140120/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.2 20140120 (Red Hat 4.8.2-16) (GCC) 
[ry@localhost ~]$ icc -V
Intel(R) C Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.0.064 Beta Build 20140530
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

icc: NOTE: The Beta evaluation period for this product ends on 25-sep-2014 UTC.

0 Kudos
Ryan_G_
Beginner
670 Views

The last update I see is dated June 20th (Update 1)

~ry

0 Kudos
Om_S_Intel
Employee
670 Views

It works also in OSX using clang environment

$ uname -a
Darwin nmicl-lab4.rr.intel.com 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun  3 21:27:35 PDT 2014; root:xnu2422.110.17~1/RELEASE_X86_64 x86_64
$ icl -std=c++11 bug.cxx -o bug -O0
$ ./bug

$ icl -V
Intel(R) C Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.0.052 Beta Build 20140528
Based on Clang version 3.4.0
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

icl: NOTE: The Beta evaluation period for this product ends on 25-sep-2014 UTC.

0 Kudos
Om_S_Intel
Employee
670 Views

The new version is not yet available for public.

0 Kudos
Sukruth_H_Intel
Employee
670 Views

Hi Ryan,

             As Om pointed out, we are not seeing any issues(seg fault) with lambda using icc compiler. This is the configuration i am using, infact i am using the same version of the icc compiler as your's , but i was not able to get the same version of gcc:-

shv@dpdknf01:~/quad$ gcc --version
gcc (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

shv@dpdknf01:~/quad$ icc -V
Intel(R) C Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.0.064 Beta Build 20140530
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

icc: NOTE: The Beta evaluation period for this product ends on 28-aug-2014 UTC.

shv@dpdknf01:~/quad$ icpc -std=c++11 shared_ptr.cpp  -o shared_ptr.exe


shv@dpdknf01:~/quad$ ./shared_ptr.exe


shv@dpdknf01:~/quad$ ldd --version

ldd (GNU libc) 2.12

Could you please try updating your gcc and check if you are facing the same issue?

Regards,

Sukruth H V

0 Kudos
Ryan_G_
Beginner
670 Views

Sukruth,

Two things

1) you are not using the compiler options I specified, namely -O0

2) the gcc version and associated libraries I am using (default on RHEL 7) are _newer_ than what you are using (compare output in posts), so that would be a downgrade and not an upgrade. Downgrading the standard libraries below system installation default is not something we are interested in.

~ ry

0 Kudos
Ryan_G_
Beginner
670 Views

Ok, so here is some code that elucidates the problem clearly. I named the struct Salamander to make relevant function calls easy to search for in assembly. This time we just have a class with a member pointer to an int. Any time the copy constructor is invoked, the address of the pointer from the class being copied is printed along with the call site function. Simple stuff. The meh() function just creates an object prints it's member pointer address captures the object by value in a lambda that prints the address and then prints out the address of the member object in the lambda function. A _correct_ execution of this code should print the same address 4 times. Now consider the following executions from g++, clang++ and icpc. I am attaching a tgz with the code and a bash script to build, if you do not have clang on your system you can comment the clang lines out. This behavior was indeed causing the crash in the previous version of the code because the shared pointer constructor was being handed garbage.

$ ./bug_gcc 
meh
0x83a010
Salamander
0x83a010
operator()
0x83a010
main
0x83a010

$ ./bug_clang 
meh
0xc12010
Salamander
0xc12010
operator()
0xc12010
main
0xc12010

$ ./bug_icc 
meh
0x24b0010
Salamander::Salamander
0
Salamander::Salamander
0
lambda []()->void::operator()
0
main
0x24b0010

#include <iostream>

using namespace std;

struct Salamander
{  
  int *s{new int};
  Salamander(){*s = 1;} 
  Salamander(const Salamander &x)
  {
    cout << __func__ << endl;
    cout << x.s << endl;
    s = x.s;
  }
}; 

Salamander meh() 
{  
  Salamander c{};  
  cout << __func__ << endl;
  cout << c.s << endl;
  auto l = () -> void 
  { 
    cout << __func__ << endl;
    cout << c.s << endl;
  }; 
  l();
  return c; 
} 

int main() 
{  
  Salamander s = meh();  
  cout << __func__ << endl;
  cout << s.s << endl;
}

 

0 Kudos
Sukruth_H_Intel
Employee
670 Views

Hi,

    Thanks for the testcase. I was able to reproduce the issue and escalated to our engineering team. I would update you on this issue soon.

Regards,

Sukruth H V

0 Kudos
Reply