I have a code with possible floating point overflows which cannot be managed by checking arguments of functions. I have to define _matherr and throw an exception from inside it in order to give a chance to caller to manage the problem.
There is something strange: in Debug build, _matherr is called as supposed, but not in Release. I use CodeGear C++ Builder 2007. Under MSVC 2010 the handler works fine, but I need VCL features for the whole application. Googling gives nothing but messages about _matherr not working in DLL (that is known from documentation).
And my question is: what could be the reason for _matherr to not work in Release?
// One of the methods with overflows.
double DoubleExponential::F(double x) const
{
try
{
double y=pow(fabs(x),a);
return 0.5 + sign(x)*G(y,1/a)/(2*G(1/a));
}
catch(PowExpOverflow)
{
return 0.5;
}
}
// Exception.
struct PowExpOverflow {};
int _matherr (struct _exception *a){
Application->MessageBox("Inside custom _matherr", "", MB_OK);
if (a->type == OVERFLOW)
if (!strcmp(a->name,"pow") ||
!strcmp(a->name,"powl") ||
!strcmp(a->name,"exp") ||
!strcmp(a->name,"expl"))
{
throw PowExpOverflow();
}
return 0;
}
The problem is due to bug in the dynamic RTL which I use in the release build (description). The bug was not fixed in the version of IDE I use, so the only working solution is to upgrade to a higher version. Nevertheless, having a clear explanation helps a lot.
Related
I'm noticing some strange behavior while stepping through my code with the debugger, similar to the problem described in this question.
For context, I have two VS2010 projects in my solution: a test executable, and a static library. Inside the library source file I have the following functions:
double LibClass::getFoo()
{
double num;
num = foo();
return num;
}
double LibClass::foo()
{
double A[65000];
return 5.0;
}
This runs fine, and the debugger can step through these functions no problemo.
If, however, I increase the size of A as follows:
double LibClass::foo()
{
double A[66000];
return 5.0;
}
The debugger pops up a "No Source Available" tab when I step into foo(). I can still step through getFoo(), and foo() still returns 5.0, so there doesn't appear to be anything wrong with the code - just the debugger. Any idea what might be happening here? My only guess is that there must be some sort of limit to how much stack space the VS debugger can monitor for a given call. Is this the case? If so, how can I increase it?
lately I have been faced with a strange problem that a simple source did not want to compile. I was looking for solutions (and cause) in many sites but without good effects (except bugs reports but I have not found there direct cause ).
Below I present simple code to reproduce that situation:
struct Foo {
Foo() : m_x( true ) {}
__property bool x = { read=m_x };
private:
bool m_x;
};
template<typename T>
struct TMyPointer {
T * m_ptr;
TMyPointer( T * ptr ) : m_ptr( ptr ) {}
~TMyPointer()
{
delete m_ptr;
}
T * operator->() const
{
return Get();
}
T * Get() const
{
if( m_ptr == NULL )
; // some error handling
return m_ptr;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TMyPointer<Foo> bar( new Foo );
if( bar->x && 1 == 1 ) ; // Failed
if( 1 == 1 && bar->x ) ; // OK
if( !!bar->x && 1 == 1 ) ; // OK
if( bar->x == true && 1 == 1 ) ; // OK
if( (bar->x) && 1 == 1 ) ; // OK
return 0;
}
Compiler has failed to compile first condition inside main function. What stranger compilation of other equivalent conditions is finished successfully.
That's behavior I have only during release compilation. To reproduce I have used Embarcadero® C++Builder® XE5 Version 19.0.13476.4176
Error message: [bcc32 Fatal Error] File1.cpp(43): F1004 Internal
compiler error at 0x14470090 with base 0x14410000
Anybody knows what is the problematic in above example? Maybe usage templates with properties mechanism is the cause?
In my case is simple solution it seems to be problematic condition inside Get method. When I change
if( m_ptr == NULL )
to equivalent form
if( !m_ptr )
everything compile without errors.
I am writing about it here becouse I would like to share my insights - it can be helpfully for somebody.
recently I got similar ICE (once my source code grows in size) and your solution seemingly helped for a while but not really as after some minor changes in code ICE resurfaced again. Based on the behavior of mine problem:
IDE: BDS2006 Turbo C++ explorer (its version of BCB between BCB6 and RAD)
Huge win32 project (several MBytes of code involving USB,OpenGL,CAD/CAM)
Each part of code is tested for years and compilable separably problem occurs once they together and code grows too big
Project compiles fine at first run but after that any recompile fails
The temporary workaround was to close IDE, delete all obj,tds,exe,... files restart IDE and compile again.
I assumed compiler and or IDE leaks or overwrites some parts of itself corrupting its functionality. As the problem persist after IDE restart without deleting temp files I assumed it has something to do with debug info stored in them.
So I played with Project->Options->Debugging settings and turning off this:
Inline function expansion (-vi)
Helped (not even IDE restart or temp file removal was needed).
Don't have enough reputation to upvote or comment someone else's posts, but I have recently found the same solution as in #Spektre reply.
Disabling Inline function expansion fixed our multiple-year problems with completely unrelated internal compiler errors on random projects. We only experienced them on MSBUILD scripts in Release config.
I found this out by going over all the compiler options in Release config that were different from Debug config and changed them one-by-one to match Debug config through msbuild parameters for the entire solution/projectgroup. And eventually it started to build without any errors when I've disabled Inline function expansion option.
These problems happened and I confirmed the fix on C++ Builder XE5;
This kept on resurfacing at random for as long as I can remember (Borland C++ 2006 and later)
The older developers used to try and revert latest commits until it started compiling again... Which is a pain in the behind.
Anyone looking for solution to pass a parameter to an MSBUILD command (for all targets in the script) add this line to the msbuild.exe call:
msbuild.exe Targets.xml /p:BCC_InlineFunctionExpansion=false /t:Build
I'm working in Visual Studio 2012. In Debug mode the program works fine, however, when changed to release mode the program fails on the call to element_to_mpz() which is called by the PBC function element_pow_zn()
I'm using MS VC++ Convertion of PBC from their download page.
The call stack seems to indicate there is an error on a call to _realloc(). I believe I found the line responsible. In the PBC source, line 133 of montfp.c (the _mpz_realloc() call)
static void fp_to_mpz(mpz_ptr z, element_ptr e) {
eptr ep = e->data;
if (!ep->flag) mpz_set_ui(z, 0);
else {
// x is stored as xR.
// We must divide out R to convert to standard representation.
fptr p = e->field->data;
mp_limb_t tmp[2 * p->limbs];
memcpy(tmp, ep->d, p->limbs * sizeof(mp_limb_t));
memset(&tmp[p->limbs], 0, p->limbs * sizeof(mp_limb_t));
/**************************************************************************
* The line I believe to be failing - However I can't step into PBC.dll as
* I do not have the symbols.
**************************************************************************/
_mpz_realloc(z, p->limbs);//This is a call into the GMP library
mont_reduce(z->_mp_d, tmp, p);
// Remove leading zero limbs.
for (z->_mp_size = p->limbs; !z->_mp_d[z->_mp_size - 1]; z->_mp_size--);
}
}
The code I am using to actually call element_to_mpz() is:
bswabe_cph_t*
bswabe_enc( bswabe_pub_t* pub, element_t m, char* policy )
{
bswabe_cph_t* cph;
element_t s;
cph = (bswabe_cph_t*)malloc(sizeof(bswabe_cph_t));
element_init_Zr(s, pub->p);
element_init_GT(m, pub->p);
element_init_GT(cph->cs, pub->p);
element_init_G1(cph->c, pub->p);
cph->p = parse_policy_postfix(policy);
element_random(m);
element_random(s);
/****************************************************
* The call to element_to_mpz() is in element_pow_zn()
*****************************************************/
element_pow_zn(cph->cs, pub->g_hat_alpha, s);
element_mul(cph->cs, cph->cs, m);
element_pow_zn(cph->c, pub->h, s);
fill_policy(cph->p, pub, s);
return cph;
}
The above code is from CPABE - Which is a library for policy based encryption. The arguments pub, m, and policy are all properly initialized from the calling environment.
I'm not sure if this is a bug in the CPABE code, the PBC, code or a bug in GMP. (since that's where _mpz_realloc() is defined)
Any help would be greatly appreciated.
To fix this issue I replaced the GMP requirement with MPIR. It can be built with VS2012 and used as a drop-in replacement for GMP. After switching to this library the issue went away.
I'm guessing the cause of my issue was a bug in GMP-4.1. Since I also couldn't get GMP-5.1 compiled and working with VC++ I could never verify that the bug is actually gone from GMP.
I got a dll with the following prototype:
DLL_EXPORT std::list<std::wstring>* c_ExplodeWStringToList(std::wstring in_delimiter, std::wstring in_string, int in_limit);
The application uses this like that:
std::list<std::wstring>* exploded = mydllclass->c_ExplodeWStringToList(L" ", in_command.c_str(), 0);
This works great under XP 32, but when I try this at home with my Vista 64 my program just closes itself. No error and no warning?
Some days ago the DLL was returning the list directly - no pointer. But I switched to VC++ 2010 Express, and I could not compile my DLL without this modification.
Anything I am not seeing here?
Thank you :)
Update:
DLL_EXPORT std::list<std::wstring>* c_ExplodeWStringToList(std::wstring in_delimiter, std::wstring in_string, int in_limit)
{
std::list<std::wstring>* returnlist = new std::list<std::wstring>();
std::list<std::wstring>* stringlist = new std::list<std::wstring>();
UINT pos = 0;
while(true)
{
pos = in_string.find(in_delimiter, 0);
if(pos == std::string::npos)
{
stringlist->push_back(in_string.substr(0, pos));
break;
}
else
{
stringlist->push_back(in_string.substr(0, pos));
in_string = in_string.substr(pos + in_delimiter.length());
}
}
// ****
// Here is missing some code I've commented out while searching for the error.
// ****
returnlist = stringlist;
return returnlist;
}
T
I didn't dig into the code, but a conclusion I came to regarding working with DLLs is to not return anything but primitive types from DLL functions. This is because due to different compilers or different switches or project settings structs and classes are not aligned the same not have the same size in the DLL and in the code calling the DLL.
So returning a list from a DLL might be considered malformed in the caller application.
Same thing regards throwing exceptions from a DLL - the class thrown might be misinterpreted by the catching code.
So, best is export only C functions that return primitive types (to denote error codes).
I have a unit test project based on UnitTest++. I usually put a breakpoint to the last line of the code so that the I can inspect the console when one of the tests fails:
n = UnitTest::RunAllTests();
if ( n != 0 )
{
// place breakpoint here
return n;
}
return n;
But I have to reinsert it each time I check-out the code anew from SVN. Is it possible to
somewhat place the breakpoint by the compiler?:
n = UnitTest::RunAllTests();
if ( n != 0 )
{
// place breakpoint here
#ifdef __MSVC__
#!!!$$$??___BREAKPOINT;
#endif
return n;
}
return n;
Use the __debugbreak() intrinsic(requires the inclusion of <intrin.h>).
Using __debugbreak() is preferable to directly writing __asm { int 3 } since inline assembly is not permitted when compiling code for the x64 architecture.
And for the record, on Linux and Mac, with GCC, I'm using __builtin_trap().
DebugBreak(void)
From Winbase.h.
MSDN
You could use this in C or C++
__asm
{
int 3
}
If you are using VC6 (yes, outdated but still in use in some places/projects), DebugBreak() will work but you may end up in some obscure location deep withing Windows DLLs, from which you have to walk the stack up back into your code.
That's why I'm using ASSERT() in MFC or assert() in "standard" code.
Your example would work like this:
n = UnitTest::RunAllTests();
ASSERT(n == 0);
//assert(n == 0);
return n;
If you don't need a result and want it just for debugging, you can also do
if(0 != UnitTest::RunAllTests())
{
ASSERT(FALSE);
//assert(false);
}
How about using a Debug or Trace method to output the console info. That may be a better approach than relying on breakpoints.
How often do you check out the project from SVN? This is typically something I only do once per project, or when I rebuild my PC.
If you also checkin the project files, the breakpoints should be stored in the project files.
I think it is in the .suo file. You could also put that under SVN control if you wanted, though I prefer not to.