tags:

views:

36

answers:

1

I have a basic solution file (.sln) where I was able to reproduce a problem I have been facing recently.

It contains 3 projects: 1.) MathTest.lib - containing methods that might cause a mathematical error, like acos(1.1). 2.) MathTestDll.dll - calls the methods from the above lib. 3.) UnitTest.exe - calls the exported method in the DLL that should cause the error.

What I'm trying to do is fairly simple: The following code contains the _matherr() routine and should ideally link fine. The call to acos() with a value of 1.1 is invalid (invalid input) and should cause an error which should be handled by the implemented _matherr() handler. I hope I'm right about the behavior of _matherr(). Please let me know. MathTest.lib

#include "MathTest.h"
#include <iostream>
#include <math.h>

int _matherr(_exception* _Except)
{
    std::cout << _Except->name;
    return -1;
}

void MathTest::ThrowMatherr(float par)
{
    float result = acos(par);
    std::cout << result;
}

This 'ThrowMatherr()' method will be called by the DLL as follows: MathTestDll.dll

void MatherrCaller::CauseMatherr()
{
    MathTest* mathtest = new MathTest();
    mathtest->ThrowMatherr(1.1);
}

which is then exported as:

extern "C" __declspec(dllexport) void CallThisToCauseMatherr();

void CallThisToCauseMatherr()
{
    MatherrCaller* caller = new MatherrCaller();
    caller->CauseMatherr();
}

This exported method will be called by a simple test. UnitTest.exe

#include <windows.h>

typedef void (*METHODTOCALL)(); 

int main()
{
    HMODULE module = LoadLibrary((LPCSTR)"..\\Debug\\MatherrTestDll.dll");
    if(module != NULL)
    { 
        METHODTOCALL ProcAdd = (METHODTOCALL) GetProcAddress(module, (LPCSTR)"CallThisToCauseMatherr"); 
        if (NULL != ProcAdd)
        {
            (ProcAdd)();
        }

        FreeLibrary(module); 
    }

    return 0;
}

All methods get called fine. But the acos() method which has been passed invalid input never calls the _matherr() error handler. Please let me know how I can fix this.

I had to make the question detailed to get my point through. Please don't mind.

A: 

It is explicitly mentioned in the documentation for _matherr:

For special error handling, you can provide a different definition of _matherr. If you use the dynamically linked version of the C run-time library (Msvcr90.dll), you can replace the default _matherr routine in a client executable with a user-defined version. However, you cannot replace the default _matherr routine in a DLL client of Msvcr90.dll.

You'll need to put the override in the EXE module. Alter your unit test to accommodate this.

Hans Passant
But, do you think there's a solution given the existing scenario? I need to keep the definition in the lib (system design constraint) as the caller is another managed dll. Putting it in the EXE would be a temporary solution for unit tests.
Elroy
Documentation source?
Elroy
Hans, what other error handling mechanism would you suggest?
Elroy
Which question do you want me to answer first?
Hans Passant
Thanks for the answer. I found the doc source. I understand that that's a lot of questions. But I'm really curious. Could you please direct me to a possible alternate solution?
Elroy
I also understand that special error handling using _matherr won't work in my case.
Elroy
I dunno, your code snippet is far too generic to recommend something else. If this is called from managed code, and you don't export any pointers or class objects from your DLL, then technically building the unmanaged DLL with /MT is possible. Not much else you can do, you cannot tinker with _control87 in a managed app.
Hans Passant
Thanks Hans. I'll do a check and post an answer if I can find one.
Elroy