-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Segmentation Fault with Intel Compiler #58
Comments
This is weird. Can you compile with debug info ( |
Yes, the address looks more like a data address. Here's what I get from gdb:
The correct formatImpl function is compiled into the program, but for whatever reason, the address is not properly stored in m_formatImpl. Another weird thing is that the address stored in m_value seems to point to a function?! When I step through the program, the addresses seem to be correct inside the constructors tinyformat::detail::FormatArg::FormatArg and tinyformat::detail::FormatListN<1>::FormatListN:
Once I step out of the tinyformat::detail::FormatListN constructor, however, something seems off. Inside tinyformat::vformat I have
and in the next step in tinyformat::detail::formatImpl I get
I don't know why, but something seems to be going wrong when assigning to FormatListRef. When I debug using
|
Wow, great sleuthing. That's exactly the information we need (I can't track this down as I don't have an icc compiler license, though I applied for one.) To me this is looking rather like a bizarre compiler bug. The other option is that I'm committing some obscure form of UB somewhere by creating my own quasi-vtable-like thing with the At this point I think the best option is to progressively minimize tinyformat.h by deleting functionality until you've got a minimal reproduction. Then we might discover exactly what triggers this.
It looks like the pointer Another option for debugging here might be to just |
I created a small example (I don't know if it's actually minimal but it should be close) to recreate the problem: class FormatArg {
public:
FormatArg(const int& value)
: m_value(static_cast<const void*>(&value)), m_formatImpl(&formatImpl) {}
void format() const {
m_formatImpl(m_value);
}
private:
static void formatImpl(const void* value) {
const int true_val = *static_cast<const int*>(value);
}
const void* m_value;
void (*m_formatImpl)(const void* value);
};
class FormatList {
public:
FormatList(FormatArg* args) : m_args(args) {}
friend int main(int argc, char** argv);
private:
const FormatArg* m_args;
int m_N;
};
class FormatList1 : public FormatList {
public:
FormatList1(const int& arg) : FormatList(&m_formatterStore[0]),
m_formatterStore{ FormatArg(arg) } {}
private:
FormatArg m_formatterStore[1];
};
FormatList1 makeFormatList(const int& arg) {
return FormatList1(arg);
}
int main(int argc, char** argv) {
// This gives a segfault when using icpc
makeFormatList(argc).m_args[0].format();
// This would be fine...
// FormatList1(argc).m_args[0].format();
return 0;
} The segfault is introduced in the I can't find any UB in this example, but that doesn't mean anything. However, a further indication of a compiler problem is that when you omit FormatList::m_N from the class definition, there's no segfault. |
I can't see any problem with this code either. I think this is minimal enough that you could report it upstream to icc and see what happens.
If you can find a workaround you can put behind a small |
I posted the issue on the Intel Developer Forum and someone spotted the problem. To fix the issue, |
When copying a detail::FormatListN object, the m_formatterStore must also be copied, otherwise the pointer in the parent FormatList class are possibly invalid. This addresses the segfault explained in #58. The issue arises when makeFormatList returns an object which holds a pointer to memory created for the temporary object on the stack.
Great! A big thanks to whoever pointed that out, and thanks for communicating it back here. I tried clang's |
Actually there's another way we could have debugged this which I should have thought of - it's possible to get valgrind to report the read of uninitialized memory. (Though for g++ only if
|
Thanks for merging the fix. At least now I've learned that gcc & clang elide constructors even if setting |
Yes, that was surprising to me. It seems with C++17 that the language has moved to this being considered a feature of the language rather than an optimization. |
I came across a very strange problem in tinyformat v2.2.0. Even the most trivial of examples
causes a segfault when compiling with
icpc -std=gnu++11 -O0
. There is no segfault when compiling with any optimization level greater than 0.The backtrace is
I tried with two different versions of icpc
The text was updated successfully, but these errors were encountered: