Search code examples
c++c++11segmentation-faultllvm-clang

Apple LLVM 4.2 segfaults using range-based loops with references


I'm not sure whether this is an actual bug of the LLVM that comes with Xcode 4.6.3 (4H1503) or if I'm doing something really not kosher. The snippet of code is as follows

for(auto &a : matrix[j]) {
    a = false;
}

where matrix is a vector of vectors containing booleans. I've been developing with Visual Studio 2012 for a while and this didn't seem to be a problem, but then the application needs to run on a Mac as well so I went on and tested it... and I was a bit surprised that I couldn't get it to compile. Upon closer inspection, I've discovered that I was getting a full blown segfault from clang itself, which is usually indication of very bad shenanigans going on. So I quickly isolated the piece of code and changed the loop to a more peasant's version using an integer index and all that jazz. It works like a charm.

Am I correct in assuming that my original loop was supposed to be working (I've seen similar things even here in SO, and besides VS2012 didn't have anything to say, really) or am I making a gross mistake and you are really not supposed to use references like that?

I'd like to know this before reporting the bug to Apple.

EDIT

#include <vector>

using namespace std;

int main(void) {
    vector<vector<bool>> matrix = vector<vector<bool>>(10, vector<bool>(5, false));;

    for(auto &a : matrix[0]) {
        a = true;
    }

    return 0;
}

compiling with clang -x c++ -std=c++11 -stdlib=libc++ yields

0  clang 0x0000000100c57bb2 main + 12932498
Stack dump:
0.  Program arguments: /usr/bin/clang -cc1 -triple x86_64-apple-macosx10.8.0 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name rbloop.cpp -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 136 -resource-dir /usr/bin/../lib/clang/4.2 -fmodule-cache-path /var/folders/ny/y4mgzkq14db49kfh7rnvcnshqvrkjz/T/clang-module-cache -stdlib=libc++ -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /Users/af6539/src -ferror-limit 19 -fmessage-length 120 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.8.0 -fobjc-dispatch-method=mixed -fobjc-default-synthesize-properties -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o /var/folders/ny/y4mgzkq14db49kfh7rnvcnshqvrkjz/T/rbloop-AUzjp6.o -x c++ rbloop.cpp 
1.  rbloop.cpp:9:22: current parser token '{'
2.  rbloop.cpp:6:16: parsing function body 'main'
3.  rbloop.cpp:6:16: in compound statement ('{}')
clang: error: unable to execute command: Segmentation fault: 11
clang: error: clang frontend command failed due to signal (use -v to see invocation)
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.4.0
Thread model: posix
clang: note: diagnostic msg: PLEASE submit a bug report to http://developer.apple.com/bugreporter/ and include the crash backtrace, preprocessed source, and associated run script.
clang: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /var/folders/ny/y4mgzkq14db49kfh7rnvcnshqvrkjz/T/rbloop-HcbryW.cpp
clang: note: diagnostic msg: /var/folders/ny/y4mgzkq14db49kfh7rnvcnshqvrkjz/T/rbloop-HcbryW.sh
clang: note: diagnostic msg: 

********************

I'm not pasting the files mentioned at the end because they are ridiculously large and don't seem to add any information (just a bunch of library headers and then my exact code as above pasted at the end of the file). Besides, if you had the same compiler I have, you should be able to get them yourselves.


Solution

  • As Howard says, the compiler should not give you a stack trace but produce an error message and as you can see gcc does produce a good diagnostic. The reason that you receive an error is that std::vector<bool> is a specialization and this thread gives some good details. So at least in gcc and clang what you get back is a proxy that acts as a reference but since it is a temporary object you can not take a reference to it and you don't need to since changes will be reflected back, I am not sure about visual studio though. This example demonstrates what I mean.