Floating-point error when calling dll function from VBA - vba

Here is the situation. I am using MS Visual Sturio 2005 and Excel 2007. I create a dll containing a function
extern "C" VARIANT WINAPI MyFunc()
{
VARIANT res;
memset(&res, 0, sizeof(VARIANT));
::VariantInit(&res);
return res;
}
That is called from Excel VBA. This function seems to work correctly.
But there is a problem: when VBA returns from my function and tries to execute the next floating point instruction I see a window:
runtime error 6. Overflow.
This error is pretty strange. I have been investigating it the last couple of days, here are the "facts" I have collected:
1) The error shows up only after the first call to the dll. All successive calls to this function don't cause this error.
2) The error is triggered by the first (seemingly harmless) floating-point instruction in the VBA code after the control returns from the dll:
Dim dMinValue As Double
dMinValue = 10000000#
3) The project from which the dll is built contains 4 files: mydll.cpp, mydll.def, cSomeClass.cpp and cSomeClass.h.
cSomeClass is a fairly complicated class that calls code from my other libs. BUT mydll.cpp does not use cSomeClass in any way. Here is the code of mydll.cpp:
#include <OAIdl.h>
#include <float.h>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
extern "C" VARIANT WINAPI MyFunc()
{
unsigned int u;
u = _controlfp(0, 0);
_controlfp(u & ~(_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT), _MCW_EM);
VARIANT res;
memset(&res, 0, sizeof(VARIANT));
::VariantInit(&res);
return res;
}
The initial version of MyFunc() didn't have the first 3 lines (the ones messing with _controlfp()), it was causing "Runtime Error 6, Overflow" in VBA. Then I started suspecting that this error could be related to the FPU registeres (I know very little about those). When I added these 3 lines an exception was thrown when I call _controlfp() - "0xC0000090: Floating-point invalid operation.". If I leave the code as it is presented above the exception causes stack unwind (we don't get to the VARIANT res; line) and a window saying "runtime error 6. Overflow." is displayed in Excel. To sum it up, adding these 3 lines caused the floating point exception to be thrown earlier. If we catch the exception thrown in the 3rd line (with an __except clause) and ignore it (by callng _clearfp()) then no errors are reported in Excel.
A NASTY DETAIL: if I remove the files cSomeClass.cpp and cSomeClass.h from the Visual Studio project the error is not reproduced. cSomeClass.h is not includeed into mydll.cpp, but if I remove cSomeClass.* files from the project the dll size is significantly reduced.
My best guess at this point is that there are some static objects in the LIB-s referenced by cSineClass.cpp that cause this. Maybe these objects are initialized (constructed) when the dll is being loaded (according to my experiments, before to DllMain) and this somehow causes an error flag for "0xC0000090: Floating-point invalid operation." being set. When we return to Visual Basic from the dll, somethis calls _controlfp and enables the floating-point exceptions (they are turned off in С++) when raises "0xC0000090: Floating-point invalid operation." that somehow gets converted to "Runtime Error 6. Overflow." that I see in Excel. This is just a guess. Up unti now I haven't found any static objects that could be doing this.
Unfortunately I haven't been able to create a small example reproducing this error, because it shows up only when I have cSomeFile.* as part of the project. And those files require all of my libs...
If anyone knows what could be the cause of such behaviour or have suggestions about how to advance with my investigations that would be greatly appreciated.

So I have at various points had similar random issues with Excel, and you are my hero.
I found that by calling _clearfp(), it will quiet the error and return the value properly. I think the issue arises from the fact that I use _HUGE values all over the place to signify invalid floats. Which sets the flag, and causes Excel (and only excel) to barf. I've never run into any issues with runtime exceptions before in any other program.

1) Apparently, when I get into the DLL code from VBA the FPU exceptions are turned off, like if someone called
u = _controlfp( 0, 0 );
_controlfp( u & ((_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT )), _MCW_EM );
before passing control to my dll code.
2) Calling std::numeric_limits::signaling_NaN() at any point causes the _EM_INVALID flag to be set in the floating point status word (can be seen by calling _statusfp()).
3) When the control is returned from the DLL the FPU exceptions seem to be turned on. As if someone called:
u = _controlfp( 0, 0 );
_controlfp( u & (~(_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | EM_UNDERFLOW | _EM_INEXACT )), _MCW_EM );
This causes a runtime error.

Related

Why do I get “Lexical with name '$x' does not exist in this frame” when using “will leave”?

I have the following Raku code:
class Thing {
method close {
say "closed";
}
};
for 1..1000 {
my $x will leave { .close } = Thing.new;
}
Running it, I get the error:
Lexical with name '$x' does not exist in this frame
in block <unit> at c.raku line 7
Interestingly, this only happens if the number of iterations is high enough (with 500 or 100, I do not get any error messages).
If I change the body of the cycle to
my $x = Thing.new;
LEAVE $x.close;
then everything works without errors as well.
What is happening here? Did I misunderstand the will leave construct? (It seems to me the two versions should be equivalent.)
EDIT: Further observation – when running the code multiple times, the error appears nondeterministically. This suggests that the problem is somehow connected to garbage collection, but I am still confused as to what actually happens here.
I am using Rakudo v2021.03.
This is a bug. Have made an issue for it: https://github.com/rakudo/rakudo/issues/4403
I suggest using the workaround in the meantime.

VBA Constants List as Arguments and Assignment Statements

Is there a way in VBA to create classes and/or methods that have a limited list of acceptable constants to use as arguments or in assignment statements?
These exist already in VBA per the images below:
I would like to incorporate this in my classes.
It's not a limited set of constants. You type xlsheethidden the program sees 0. The compiler puts 0 into the program. Nothing stops you doing this. ReportCS1.Visible = 1,000,000. It's an aid to writing programs, it doesn't form part of the finished program.
If you want to limit what can be passed then you'll need to write code checking what was passed, if wrong do err.raise(&h80070000 OR 13, blah,blah, blah).
This turns a WinError into a HResult - 13 seems resonable. = 0x8007000d
//
// MessageId: ERROR_INVALID_DATA
//
// MessageText:
//
// The data is invalid.
//
#define ERROR_INVALID_DATA 13L
Tim Williams answered my question in his comment. Thanks Tim!
You can create an Enum See: cpearson.com/excel/Enums.aspx

MATLAB Genetic Algorithm "Subscripted assignment dimension mismatch" Error

When trying to use the Genetic Algorithm solver in MATLAB, I'm getting the following "Subscripted assignment dimension mismatch" error: Error Message Pastebin
Now, it says the error has to do with the fitness function at the end, but when I test my fitness function separately, it works without errors. I can also link the code for my fitness and constraint functions if that would help.
Thank you very much!
I think I see what is happening... Because one of the appendages to CDraft is inside the if, you don't always return the same length vector - i.e., you return a constraint vector the first time, it preallocates a matrix for your constraint output, then the next time round you give it back something that doesn't fit in this matrix, so you get the error.
The clue is in the error stack: at the top of the stack we have
Subscripted assignment dimension mismatch.
Error in C:\Program
Files\MATLAB\R2012b\toolbox\globaloptim\globaloptim\private\gaminlppenaltyfcn.p>i_convectorizer
(line 135)
Clearly this is not a function you've written, and inspecting your function there's nothing that should cause this error. The end of the error gives another clue
Caused by:
Failure in initial user-supplied fitness function evaluation. GA cannot continue.
The ga function is reporting an error in the bit of the code that handles user-supplied constraints. It is likely that this whole bit of code (the call to the user-supplied function and other associated lines) are all within one try...catch statement that returns this error. Something like this:
try
c = userConFun(x);
if isempty(cHistory)
cHistory = zeros(length(c), 1000); % or whatever
end
cHistory(:, currentIterationIndex) = c;
catch err
error('Failure in user-supplied fitness function blah blah blah');
end
Consequently, it looks like the error came from your function, even though it occurred after your function returned.

Parameter 3 is not constant in call of system task $fwrite

I am using Xilinx ISE 10.1 to run some verilog code. In the code I want to write the register values of 3 registers in a file, cipher.txt. The following is the code snippet:
if (clk_count==528) begin
f1 = $fopen("cipher.txt", "w");
$fwrite(f1, "clk: %d", clk_count[11:0]);
$fwrite(f1, "plain: %h", plain[31:0]);
$fwrite(f1, "cipher: %h", cipher[31:0]);
$fclose(f1);
end
At the end of execution, the contents of cipher.txt is found as:
clk: %dplain: %hcipher: %h
There is no other error encountered, but a warning comes up corresponding to the 3 fwrite's:
Parameter 3 is not constant in call of system task $fwrite.
Parameter 3 is not constant in call of system task $fwrite.
Parameter 3 is not constant in call of system task $fwrite.
The values of the registers clk_count and cipher change on every clock cycle (value of register plain remains constant throughout), and the values are written to cipher.txt when clk_count equals 528 (indicated by the if statement)
Can anybody provide some insight and/or help me get past this hurdle?
Thanks.
It appears that ISE expects the arguments to $fwrite to be constant. The warnings are referring to clk_count[11:0], plain[31:0], and cipher[31:0], which are not constant. By definition they are changing each cycle so they are not known at compile time. This also explains why they are not printing and you are seeing %d and %h in the output.
There is nothing to my knowledge in the Verilog spec that requires the arguments to $fwrite be constant. The same code works as expected with Cadence Incisive. My guess is that it's a limitation of ISE, so you may want to check with Xilinx.
Possible work-arounds:
1) Use $swrite to create a string with the proper formatting. Then write the string to the file.
2) Try using an intermediate variable in the calls to $fwrite. Maybe the part-selects are throwing it off. e.g.
integer foo;
foo = clk_count[11:0];
$fwrite(... , foo , ...);
Either of those might work, or not.
Out of curiosity, if you remove the part-selects, and try to print clk_count without the [11:0] , do you get the same warnings?

Understanding what Fault, Error and Failure mean

Consider the following class:
class Xyz {
public int count;
public void numZero (int[] x) {
// Effects: if x == null throw NullPointerException
// else return the number of occurrences of 0 in x
int count = 0;
for (int i = 1; i < x.length; i++) //we have a bug here
{
if (x[i] == 0)
{
count++;
}
}
this.count = count;
}
}
I'm trying to wrap my head about what Fault, Error and Failure really mean.
Fault
From what I've come to understand, a Fault in this context would be a flaw in the code's written logic.
So in this case the Fault would be the fact that the code instructs the computer to start iterating over all elements of v with a start index of 1 instead of the expected 0.
Error
When running the above method, we always get an Error but in once instance (when v.length == 0), as what we really want is to iterate over all elements of x, but since we're starting with i = 1, that is not really happening.
With an empty vector as input, as we don't enter the for loop, so our incorrect code isn't run, meaning that the Error doesn't happen, and everything happens as should in theory.
Failure
Since our code has a Fault that in execution-time will almost always manifest in a Error, we only have a Failure when we effectively see the incorrect output.
Assuming that an Error effectively happened in my program, we only have a Failure if it is in some way visible to the outside world. That is, had I private int count; instead of public int count; I'd never ever have an Error in my class (of course it'd be the most useless class ever!). Is this right?
Is everything I said correct or am I erring in something?
Thanks
Failure: A difference from the expected result. This is the problem
you observe.
Fault: The cause of the failure.
Error: The mistake which caused the fault to occur. e.g, typos.
An example of failure, fault and error.
pre: param is an integer.
post: returns the product of the param multiplied by 2.
1. int double (int param) {
2. int result;
3. result = param * param;
4. return result;
5. }
• A call to double(3) returns 9, but the post condition says it should return 6.
• Result 9 represents a failure.
• The failure is due to the fault at line 3, ( "* param" is used instead of "* 2")
• The error is a typo, ( someone typed "* param" instead of "* 2" by mistake).
Why give three different labels for a "Bug"?
They help communicate how precisely you know what the problem is.
Saying "failure" means you know something is wrong but don't know the cause.
Saying "fault" means you know the cause, but don't know why the fault occurred.
Saying "Error" means you know why the fault occurred; e.g.: The coder was distracted by a firetruck passing by.
You could ask, "But why did the person make a typo?" But that gets into into human factors and out of the scope of the question.
Source: Zhen Ming (Jack) Jiang - EECS 4413, Software Testing, York University.
First, a failure occurs whenever the actual service delivered by a system deviates from its expected service. Note that since even specifications can go wrong, the definition does not rely on them.
Second, an error is the part of the system state that may lead to a failure. The state of the system can go wrong but never reach the output, thus not lead to a failure.
Third, a fault is the cause of an error. It can be a design fault, a cosmic ray or whatever. If, as you point out, the fault is not activated, no error is produced.
Take a look at the basic concepts and terminology of dependability for more information.
Error is a deviation from the actual and the expected result. It represents the mistakes made by the people.
Faults are the result of an error. It is the incorrect step or process due to which the program or the software behaves in an unintended manner
Bug is an evidence of Fault in a program due to which program does not behave in an intended manner
Failure is an inability of the system or components to perform its required function. Failure occurs when Faults executes
Defect is said to be detected when Failure occurs.
There are a plurality of different definitions, the one I personally prefer is the following:
Fault -> Error -> Failure
Fault: The verified or hypothesized cause of an error (malfunctions, external interference, design errors).
Error: The manifestation of a fault within a program or data structure (difference between actual output and expected output).
Failure: The event that occurs when an error reaches the service interface, altering the service itself (leads to the inability of a system or component to perform required function according to its specification).
The Error in Error/Fault/Failure refers to the human error that introduced the problem. The human error was the incorrect thinking that caused the user to create an incorrect for statement in your example.
Errors are hard to measure or understand. It is difficult in many cases to know what the developer was thinking when the made the error that introduced the fault. That is why they like to differentiate between error and fault. We can see that there is a fault in the code, but it is hard to know why the error was created. It could be that the code was correct, and then during a subsequent change, the for loop was changed.
I always remember that an Error by a programmer leads to a fault in the code that results in a failure for the user. Not all errors result in a fault. Not all faults result in failures.
The software Fault refers to a bug in the code. And it is DURING the software activity.
While software Failure is when the system misbehaves. This is observed LATER than a fault.
Fault may be the cause for a Failure. Fault is "WHAT" and Failure is "WHEN".
Those are only fundamentals, but still I hope that it sheds some light on the matter.