Add raw values enumeration to fix segfaults#1312
Conversation
Works around a segfault in LLVM builds.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1312 +/- ##
==========================================
+ Coverage 24.81% 24.87% +0.05%
==========================================
Files 169 169
Lines 19631 19655 +24
==========================================
+ Hits 4872 4889 +17
- Misses 14759 14766 +7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Just had a quick initial look. So it looks like the issue here is we're dealing with methods that return an enum, whereas the last 2 PRs were dealing with methods that took an enum as an argument? |
|
Actually not a member method returning an enum, rather it's a member field of type enum? |
|
When it segfaults, is there any debug info mentioning exactly which missing virtual function it was trying to call? |
|
The segfault comes during inline int
SGPropertyNode::get_int () const
{
if (_tied)
return (static_Cast<SGRawValue<int>*>(_value.val)->getValue();
else
return _local_val.int_val;
}From what I can tell, LLVM is optimizing away the vtable from the actual As for the other calls, I believe it is also coming back to the same root cause, but the cast of the pointer from |
|
I have to say that I am not comfortable with this PR. Unless proven mistaken, the code in |
|
I mean before merging the PRs #1304 and #1311, we were using In |
|
Static casting of a parent pointer to a derived pointer is fine, as long as you are casting to a type that matches the underlying data.
Consider the following: struct Base {
Base() = default;
virtual ~Base() = default;
};
struct Derived1 : public Base {
virtual ~Derived1() = default;
};
struct Derived2 : public Base {
virtual ~Derived2() = default;
};
int main(void) {
Base * v = new Derived1();
Derived2 *v2 = static_cast<Derived2*>(v);
Derived1 d1;
Derived2 * pd1 = static_cast<Derived2*>(&d1);
return 0;
}$ g++ ./test.cc
./test.cc: In function ‘int main()’:
./test.cc:20:22: error: invalid ‘static_cast’ from type ‘Derived1*’ to type ‘Derived2*’
20 | Derived2 * pd1 = static_cast<Derived2*>(&d1);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~The first cast is not shown as an error, because we have laundered the type through the base pointer. When directly casting, without laundering the pointer, the compiler knows that it is an invalid cast. |
|
Thanks @bramoore. I stand corrected. |
There was a problem hiding this comment.
Unless I have misunderstood the purpose of the patch, the class SGRawValueMethodsIndexedEnum also needs to inherit from SGRawValue<int> ?
Also I am unsure why SGRawValueMethodsEnum::getValue returns an int while SGRawValueMethodsIndexedEnum::getValue is returning the type T?
jsbsim/src/input_output/FGPropertyManager.h
Lines 76 to 79 in 5200260
|
And I'm wondering if using jsbsim/src/simgear/props/props.cxx Lines 567 to 574 in 5200260 I guess that dynamic_cast<SGRawValue<int>*>(_value.val) would return void for the case at stake ? So something along the lines below would help intercepting any future similar occurrence ?
if (_tied) {
auto raw_value = dynamic_cast<SGRawValue<int>*>(_value.val);
assert(raw_value); // Intercepts errors when compiled with NDEBUG.
return raw_value->getValue();
}
else
return _local_val.int_val; This change would be implemented on our copy of SimGear only but this would help making sure that future changes are not introducing similar issues. |
|
Yep, just confirmed that Any reason not to also ask the maintainers of SimGear to switch to using |
Nice ! At least we now have a way to intercept these errors without recurring to some specific optimization from one compiler. However as far as I am aware
Why not ? However I am not sure they have creative usages of |
|
Checking in to see what the next steps are. Is there anything more you need from us? |
|
I think we should go-ahead with this PR, but leave the |
Yep ! I was about to say the same thing. So I 've pushed the "merge" button. |

After the fine work done in #1304 and #1311, my colleague is still getting a segfault when building with
clang -flto=full -fvirtual-function-elimination -fvisibility=hidden.We believe the issue is from how the code is converting from a generic type to an Int type for Enum use. In this case, a casting occurs, changing the underlying object type, and thus swapping from an object type for which the vtable has been optimized away to a type that expects to have a vtable.
This PR shows one way to work around the issue. With this patch, we confirm that the JSBSim HEAD successfully runs on each of the CPUv8 inputs without segfaulting. Please let us know what you think. Thanks!
#834