I'm trying to convert a double to float as well as various integer types inside a dll, which is used as a Game Maker extension. I don't need a sensible result if the double doesn't fit the range of the target types, so I simply used a static_cast.
Everything works as intended when I call this code from my own test C++ application, but when it's called from Game Maker, range errors raise SIGFPE for some reason, which leads Game Maker to terminate my program with an error message.
I don't need sensible results for out-of-range conversions, but crashing is a no-no. I tried using llround instead of a cast, but it also raises the signal.
I also tried catching the signal myself by using signal(SIGFPE, SIG_IGN); right before the conversion, but it didn't change the behaviour at all. Maybe the ominous comment in the mingw signal.h has something to do with that: "SIGFPE doesn't seem to work?"
I checked the source code of a different dll used in a Game Maker extension, and the binary provided by the author performs simple cast conversions without a problem. When I compile the source myself however, the SIGFPE problem is present again. I am guessing that the author used a different compiler, but I'd prefer to stay with mingw if possible.
So, how do I either perform these conversions safely, or prevent the signal from being generated when I perform them with a simple cast? I'm using mingw-g++ 4.5.0 to compile at the moment.
Here's the function where the problem happens:
template<typename ValueType>
static double writeIntValue(double handle, double value) {
boost::shared_ptr<Writable> writable = handles.find<Writable>(handle);
if(writable) {
// Execution reaches this point
ValueType converted = static_cast<ValueType>(value);
// Execution doesn't reach this point if e.g. ValueType
// is short and value is 40000
writable->write(reinterpret_cast<uint8_t *>(&converted), sizeof(converted));
}
return 0;
}
The good solution is to perform the conversion correctly by ensuring that the source value is within the range of the target type before casting. So my code from the question could be corrected like this:
ValueType converted;
if(value >= std::numeric_limits<ValueType>::max()) {
converted = std::numeric_limits<ValueType>::max();
} else if(value <= std::numeric_limits<ValueType>::min()) {
converted = std::numeric_limits<ValueType>::min();
} else {
converted = static_cast<ValueType>(value);
}
Another option is to use numeric_cast from the Boost libraries, which throws an exception if the source value is out of range, so it has defined behaviour for all conversions.
The documentation of the Boost Numeric Conversion library contains some helpful information about how the standard defined certain conversions.
Thanks to rve for providing the correct suggestion in his answer, but unfortunately his example code is flawed, and I wanted to add some additional pointers that helped me.
Since you are using a DLL, are you sure the DLL is compiled in the same way as the program expects it? Maybe some 32/64 bit mismatch?
Also, SIGFPE can also be raised when there is an under/overflow when converting.
You can enable/disable the signal raised by this overflow by setting the mask using _FPU_SETCW (it's in fpu_control.h) My guess is that Game Maker enables this and your test program not.
I never tried this and I'm not sure mingw also has this but I hope this helps a little.
edit:
Why not making sure an overflow does not happen?
Something like:
if (value > std::numeric_limits<ValueType>::max())
{
value = std::numeric_limits<ValueType>::max();
}
else if (value < std::numeric_limits<ValueType>::min())
{
value = std::numeric_limits<ValueType>::min();
}
ValueType converted = value;
probably it's not related with conversion itself but with trying to access invalid memory (maybe stack corruptions or something like that). can you provide some code snippet?
Related
I have a C++ template function that looks like
template <class T>
void Item::SetValue(T value){
std::ostringstream oss;
oss << value;
this->value = oss.str();
}
It's been working fine for years until today when my OS (vxworks) threw an SPE exception at me. This basically means I was trying to do floating point arithmetic in a task context that doesn't allow it. This would be fine if I was indeed doing any floating point stuff, but I in fact am just passing a uint32_t to this function. However there are 100s of calls to this function elsewhere from other modules, so who knows what C++ has generated.
I need to know for sure this is the problem (I'm 99% sure) so I want to know if there's any way for me to figure out what function C++ compiler generated for that call. Is there any way?
I may have to ask a new question. I found in the debugger that it is using Item::SetValue<unsigned int> and that it is actually throwing the exception in std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char>>>::do_put (at least, i think). This is the instruction output, and it is failing in evstdd which is definitely in the SPE set. Still don't know why it wants to do any floating point stuff.
Is it possible that
oss << value
Will always treat value as a float, just in case? IE in std::num_put? I don't know how I'll get around this.
Instruction set
Yes, you can use type_traits
if(std::is_same_v(T, uint32_t)) { /*debug info*/ }
The classical solution is to add to the body of the function:
static_assert(!std::is_floating_point_v<T>);
I'm writing a C++ class that stores some double values in a vector (called mpValues) and calculates their average. When constructed, the value array is empty, so performing this calculation would return 0.0/0.0.
I decided that asking for the mean of zero values is a error. Therefore, it would be best to return NaN and display an error message, so that the user is made aware of that problem.
The code looks like this:
double Average::CalculateAverage() const
{
if(mpValues->size() == 0){
std::cerr << "Instance of Average at: " << this << " contains no values.\n"
<< "In this case the arithmetic mean is defined as NaN." <<std::endl;
return 0.0/0.0;
}
else{
...calculate the arithmetic mean
}
}
Is this a sensible approach, or do you have better suggestions? Usually, I wouldn't be so fussy, but this is a test for a job offer so I'd like to avoid bad decisions.
Thanks in advance!
The standard options are to return NaN, throw an exception, or return an option, such as boost::optional. There are advantages and disadvantages to each, which have been reviewed in detail by numerous people. Just do not display error messages within the function, since this violates the single responsibility principle.
You've already answered the question:
I decided that asking for the mean of zero values is an error.
Thus, there is no need to return NaN or handle zero division. You can create your own exception class (e.g. EmptyVectorError) and throw and catch it.
this is a C++ question, so we should give a C++ answer. From the single-responsibility principle (mentioned by Don Reba), we conclude that reporting an error from within your function is not really appropriate. There are two main options.
1 specify clearly that calling your average(container) with an empty container is undefined behaviour (UB). This is standard practice with many algorithms in the C++ std library. It allows you to ignore the possibility of an empty container and just return sum/size(). You may add assert(size()>0); (or similar) in debug mode.
2 explicitly allow for empty containers in the API (which I think is what you wanted to). In this case, returning sum/size() is inappropriate. It may return NaN or trigger a signal, depending on the error settings, but even a NaN is not easy to catch (I think isnan() is not a standard library function). So you must somehow return the undefined result in a clean way. This can be done by throwing an appropriate exception or by returning a type, such as boost::optional<> (suggested by usta), which explicitly allows for an undefined value that is not an error (unlike NaN with double).
I consider throwing an exception as the most appropriate way in C++ (if you go for option 2).
Change the return type to boost::optional<double>, I'd suggest.
Link to Doc
You have 2 options - either return NaN or throw an exception. What you should do, depends on the usage.
1) the client displays the mean only: then I would choose to simply return NaN. This way, the client is not forced to write error handling code for something he doesn't bother.
2) the client calculates new values using the mean: then it is difficult. By throwing an exception, you force him to handle it explicitly. This can be a good thing. On the other hand - the double value NaN can be used in calculations as far as I know. It also depends on the rest of your work. If you always use exceptions, you should use one as well. If you always use error codes, you should use NaN. If you mix - you should clean that up.
P.S.: I wouldn't write 0.0/0.0 but use std::numeric_limits instead. It's easier to read.
If I have a simple class such as...
class Rectangle
{
private:
double length;
double width;
public:
void setLength(double l) { length = l; }
void setWidth(double w) { width = l; }
void getLength() { return length; }
void getWidth() { return width; }
void getArea() { return length * width; }
};
...and the person using it calls the mutator setWidth() with an invalid argument, say -1.0, what is the correct way to handle this? When I say correct, should I for example, change the return type from void to bool or possibly an int and return a value to indicate whether or not the operation occurred successfully, or am I to allow the value to be set since theoretically it will not break anything, but any values returned as a result, say from getArea() will be garbage and the user will have to debug what he/she did wrong?
Sorry if this is a silly question, but two text books later, and I'm still not quite sure about how classes I write should be implemented for others to use.
You have a couple choices. In the real world, it will depend on who is using your class (other internal code or public API) as well as conventions agreed upon by your company.
You can:
Throw Exception
Pros:
Simple to implement
Keeps error handling code clean
Allows passing of error messages and other variables
Standard for most exceptional situations
Harder to ignore than a boolean return
Can be thrown from constructor
Cons:
Can be overused in areas where normal conditional statements should be used (this situation doesn't count)
You are introducing more "invisible" breaking points into an application. Many times users of a class don't know what exactly is going to be thrown because it either isn't documented or he/she didn't read the documentation.
Assert
Pros:
Rule of thumb: if you are going to crash, crash early
Good for situations where you as the developer call the code and have control over the input
Strong debugger support (typically)
Cons:
Gets excluded from non-debug builds so not good for times when user can still input bad data
Boolean Returns
Pros:
Quick/Easy to implement
Smaller footprint than exception handling (although this is negligible these days)
Cons:
Can't pass back any extra information to the caller (why did it break?)
Breaks down when you are trying to be consistent through your entire project and a simple boolean won't cut it
Easier to ignore compared to exceptions
Evaluate Data Type
Don't be afraid to go back and check if the data type of your property makes sense for what you are doing. In this case, it does. However, I can think of times where developers have used standard integers when they really wanted unsigned integers or strings when they really needed a single character.
You should throw an exception:
#include <stdexcept>
// ...
void setLength(double len)
{
if (len < 0)
throw new std::invalid_argument("len");
length = len;
}
Depends on the usage of the class.
If you want a user friendly message to be passed on to caller, you can put an if condition and throw an exception (e.g. std::invalid_argument) with a good description. Update the documentation and signature appropriately of course.
If you expect this should never happen in real life, but can happen in, say testing phase of the development, then I recommend using assert. As in production/release build the asserts are "removed" from code by compiler. So while testing (debug build, e.g. -DNDEBUG and/or -g option for gcc) if someone makes a mistake, you'll see a clear assertion failure, but in real/production environment no error would be reported and the extra condition won't harm the performance.
Usually when compiler is invoked with -DNDEBUG option, it's
Some references for assert and throw syntax.
Either return false; or throw something like invalid_value.
How an error should be handled is completely requirement/project dependent. If your project require to continue with wrong user input (which could be very dangerous in real life software) that's what you need to do. Similarly, if the project needs protection against wrong user input, that must be addressed.
When you design a class to be used by other user, you must make sure it can't be used any wrong way. You must fool proof your code. If any bug emerges from the software where your class will be used, you should write the class in such a way so that the bug doesn't come out from your code.
I've got a floating point exception in huge application after some changes. I tried to comment my changes and found that FPE happens when I enable one simple function call.
api::getMaxSize();
which simply returns value.
looks like this
int api::getMaxSize() { return 536870912; };
This is static member function. When I move this to header file everything works fine.
I'm confused, what can be the reson? Looks like API is in another module and linked as dynamic library, but how can this cause a problem?
added
There is function maxBox() which is template and implemented in api.h header file.
This function calls getMaxSize()
template <typename T>
static rectangle<T> maxBox()
{
return rectangle<T>(
getMinSize(), getMinSize(),
getMaxSize(), getMaxSize()
);
}
here is the calling code
if (!api::maxBox<double>().contains(box * scale)) { /* api::getMaxSize(); */ }
If I enable getMaxSize() call the program starts throwing FPE, but getMaxSize() is actually never called.
added
Found FPE in box * scale, can't understand why it was working without getMaxSize() call, but however the problem is solved. Thanks to everybody.
Thanks in advance.
Floating point exceptions (actually signals) are raised for different reasons. The main ones are:
you divide an integer by zero
an operation on signed integers overflows (unsigned integers must wrap around silently in C and C++).
As you can see, they have nothing to do with floating point numbers ! The name is historical and cannot be changed without breaking a lot of source code (there is a SIGFPE constant in <signal.h>).
It can be here that GetMaxSize returns a value which is not representable by a int.
What's the best way to use NaNs in C++?
I found std::numeric_limits<double>::quiet_NaN() and std::numeric_limits<double>::signaling_NaN(). I'd like to use signaling_NaN to represent an uninitialized variable as follows:
double diameter = std::numeric_limits<double>::signaling_NaN();
This, however, signals (raises an exception) on assignment. I want it to raise an exception on use, not on assignment.
Is there any way to use signaling_NaN without raising an exception on assignment? Is there a good, portable alternative to signaling_NaN that will raise a floating point exception when used?
After looking into this some more, it looks like signaling_NaN is useless as provided. If floating point exceptions are enabled, then calling it counts as processing a signaling NaN, so it immediately raises an exception. If floating point exceptions are disabled, then processing a signaling NaN automatically demotes it to a quiet NaN, so signaling_NaN doesn't work either way.
Menkboy's code works, but trying to use signaling NaNs runs into other problems: there's no portable way to enable or disable floating point exceptions (as alluded to here and here), and if you're relying on exceptions being enabled, third party code may disable them (as described here).
So it seems like Motti's solution is really the best choice.
What signaling NAN means is that when the CPU encounters it a signal is fired, (hence the name). If you want to detect uninitialized variables then raising the warning level on your compiler usually detects all paths that use uninitalized values. Failing that you can use a wrapper class that stores a boolean saying if the value is initialized:
template <class T>
class initialized {
T t;
bool is_initialized;
public:
initialized() : t(T()), is_initialized(false) { }
initialized(const T& tt) : t(tt), is_initialized(true) { }
T& operator=(const T& tt) { t = tt; is_initialized = true; return t; }
operator T&() {
if (!is_initialized)
throw std::exception("uninitialized");
return t;
}
};
You can write a signalling NaN into a variable without triggering an exception with something like this (nb: untested)
void set_snan( double &d )
{
long long *bits = (long long *)&d;
*bits = 0x7ff0000080000001LL;
}
It'll work most places, but no, it's not 100% portable.
Well, looking after the definition of both quiet and signaling NaN, I can't really make out any difference.
You could use the code that is used in those functions yourself, maybe it prevents an exception that way, but seeing no exception in those two functions, I think it might be related to something else.
If you want to directly assign the NaN:
double value = _Nan._Double;
Simple answer:
Do something like this in the header file and use it everywhere else:
#define NegativeNaN log(-1)
If you wish to do some kind of manipulations on them better write some extended wrapper function around exp() like extended_exp() and so on!
Your C++ implementation may have an API for accessing the floating point environment to test for and clear certain floating point exceptions. See my answer to a related question for more information.