0
Why no exception and how to ensure invalid object
Refer code below: https://www.sololearn.com/compiler-playground/cfx0suRm7SVG I have two questions in this code: 1. Why this code results in core dump? I know issue is due to obj3 as it results into division by 0 But isn't it handled due to try catch block? 2.If problem 1 is solved,how to ensure that obj3 is not valid object? In short, I would like to restrict other function call on this object and mark that object as invalid. Can anyone please help here? https://code.sololearn.com/cfx0suRm7SVG/?ref=app
20 Réponses
+ 2
MO ELomari
Optional is a great way.
I learned it's power while teaching myself Rust.
It certainly is less intimidating than pointers...
plus you have error handling built in.
Great solution.
+ 2
I learned a lot of interesting things from MO ELomari
Here is my study on the std::optional variant. Unfortunately, Sololearn does not have <format>, but that is a minor inconvenience.
I am curious about all the noexcept though. the code seems to work without them.
Also, maybe because of compiler options, I cannot use emplace unless I also define the struct ctor.
https://code.sololearn.com/c74qcNKw1i67/?ref=app
+ 2
Bob_Li
in C++17 std::optional<T>::emplace was being disabled due to faulty evaluation of a < std::is_constructible > trait of the parameter class.
constructibility is based on the ability to use constructor syntax (Type(args)). in C++20, aggregates can be initialized using constructor syntax, but in C++17 and before, they must use brace initializer "{ " syntax.
see yourself:
c++17 : https://godbolt.org/z/9P7GMxWGh
c++20 : https://godbolt.org/z/G6hPv3r1a
+ 1
The code results in a core dump because the division by zero exception is not a C++ exception and cannot be caught by a try-catch block.
To ensure obj3 is invalid, you can use a flag to mark it as such and check that flag in your functions to restrict their execution on invalid objects.
+ 1
#include <iostream>
class MyClass {
public:
MyClass() : isValid(true) {}
void doSomething() {
if (!isValid) {
std::cout << "Object is invalid." << std::endl;
return;
}
// Your regular function logic here
// ...
}
void markAsInvalid() {
isValid = false;
}
private:
bool isValid;
};
int main() {
MyClass obj3;
// Simulate an error condition
obj3.markAsInvalid();
obj3.doSomething(); // This will now indicate that the object is invalid
return 0;
}
+ 1
One idea is to use a factory method.
Pass the arguments through a function that verifies the validity of the parameters and let it decide whether or not to create the object instance.
+ 1
It sounds like what you need is C++17 std::optional ( or C++23 std::expected ), so that obj of type clsTest has two states: empty/invalid and non-empty/valid :
std::optional : https://godbolt.org/z/qe8aPf5f8
https://en.cppreference.com/w/cpp/utility/optional
https://en.cppreference.com/w/cpp/utility/expected
+ 1
Thanks @MO ELomari
+ 1
wow, I am amazed by your familiarity with the C++ labyrinth.
So many shiny new features are being introduced that it feels overwhelming sometimes. No wonder some just stick with the basics and make do with verbose constructs than try to keep up to date with the latest features.
But yes, knowing about them is a big win. Conciseness is always a good thing.
btw, adding a constructor makes the assertion pass for c++17, so emplace is still accessible. (google+stackoverflow)
https://godbolt.org/z/x94cz84cd
0
Isnt it cumbersome to check validity in each and every function of a class ? What if someone at later stage adding new method forget to add this condition ?
It is very bad of C++ if there is no alternative to this.
Anyway, thanks a lot GamerGeil Hd for your response and help.
p.s. also how to avoid core dump for division by 0 case ?
0
It's not an exception. It's an error which is determined at hardware level and is returned back to the operating system, which then notifies your program in some OS-specific way about it (like, by killing the process).
in such case what happens is not an exception but a signal ( < SIGFPE > which stands for < Signal Float Point Exceptions > ) , the operating system interrupts your program's main control flow and calls a signal handler, which - in turn - terminates the operation of your program ( program crashes by SIGFPE signal ) ,It's the same type of error which appears when you dereference a null pointer ( then your program crashes by <SIGSEGV> signal, segmentation fault ).
here's an example using the functions from <csignal> header to provide a custom handler for the <SIGFPE> signal:
https://www.sololearn.com/compiler-playground/c77Qa24OTvbj
https://code.sololearn.com/c77Qa24OTvbj/?ref=app
Note 1 : catching those signals it's NOT a way to control your program's flow even in exceptional cases. a valid program shouldn't do that. it's only useful for debugging or diagnosing purposes.
Note 2 : the signal handling is OS-dependent.
about your 2nd question can you clarify more what do you mean by invalid object.
0
Ketan Lalcheta
Here is my code for preventing instancing for invalid arguments. Perhaps you can adapt it for your use...
Also here is my modification to your code
https://code.sololearn.com/cGHXAqnp1sSq/?ref=app
https://code.sololearn.com/cXCAzBMXfp8O/?ref=app
0
Thanks @MO ELomari. It looks far better than a crash core dump.
However, you have destructor with signal as necessary part. This means object was constructed and destructed object finds code related to handle into destructor.
As far as it is avoiding crash, I am happy with this.
But in reality, My expectation is to ignore all such failed objects and perform the operations on successful object. Let me elaborate on this.
Assume that I have a display method in class which just prints a statement like welcome.
Inside main function, from all objects, this method is called. Ideally with all five successful object creation, I must get 5 welcome message on console (each due to an object). But as obj3 is failed, it should print 4 message.
0
Ketan Lalcheta
did you look at my code?
instead of relying on error messages and signals, you can use smart pointers and condition checking to get the result you want.
0
@Bob_Li,
I am sorry but this is not a valid code for production. Asking user not to call a method is cumbersome and error prone.
Better way to stop getting core dump than this one is something like what @D1M3 has mentioned (like marking a state as valid or invalid)
0
ok, I am following this thread to learn of a better method, I hope you don't mind...😎
I am confused about the part where you mentioned "asking the user not to use a method..."
The impression I got was you wanted to avoid object instancing if the constructor resulted in an invalid id n/0 ( by extension, because of an invalid constructor argument value). The invalid variable was not able to use the method because it was not instantiated, not because it was asked not to use it.
Also, the program was able to ignore the invalid constructor and continue on to the next ones without crashing .
Or maybe I am just misunderstanding the requirements...
0
Bob_Li always welcome. This platform is for us only to get help from each other and learn from each other.
In your code, you stopped calling show method to avoid the core dump or you can say run time error. In actual code, it will be very complex and one cannot predict where error would occur. So , method calling on object is very normal case.
Now concern is to avoid object construction which i have not yet got like how to do it.
Singnal is ok but it fails all other valid objects output also.
Isvalid or invalid approach mentioned here is also valid option. But it does not gurantee a stoppage of object creation. If valid or invalid state is to be followed , it has to be followed in each method of that class.
0
The core dump is natural if the invalid constructor tries to access the show method, because the object was not really constructed. That is why I commented it out. To display that the instancing was not successful.
i was under the impression that this was one of the main goals.
The probem with raising errors is that it interrupts the program. Then it cannot proceed with the construction of the next objects.
Invalid arguments passed to the constructor will still create instances, but the parameters will have the undesired values or perhaps default ones.
Other than using unique_ptr, I have not found another way to stop the constructor.
Even calling the destructor if the argument was invalid was not successful for me.
Perhaps you or some other members here can come up with a more satisfactory solution. I will surely like to learn that way..
0
Factory sounds a good option. Let me try this tomorrow morning.
0
My experiment:
https://code.sololearn.com/ckMC8x0P19Zq/?ref=app