Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

destruction of std::map, heap corruption

145 views
Skip to first unread message

Hicham Mouline

unread,
Oct 7, 2008, 3:59:08 PM10/7/08
to
{ Note that questions are better answered when posted with a minimal,
compilable standard C++ code by relevant definitions supplied and
irrelevant dependency upon proprietary features removed.

Responders are encouraged to stay within the standard C++. -mod }

Hello,
msvc2005 (main.cpp and another .cpp in a DLL)
I have 2 situations:

1)
* const black_scholes_merton<european_put>& bsmep =
black_scholes_merton<european_put>::getModel();
* pricing_model::result_set* rs = new pricing_model::result_set;
* bsmep.allOrSome(*rs, pricing_model::operation_set(pricing_model::PRICE),
epx, pmp);
* double pr = (*rs)[pricing_model::PRICE];
* delete rs;

bsmep.allOrSome is a one liner public nonvirtual member function of
black_scholes_merton<european_put>
allOrSome(result_set& res, const operation_set opset, const contract& c,
const pricing_model_parameters& mparams) const
{
res[PRICE] = 77.0;
}

class pricing_model::result_set {
public:
double& operator[](Operation);
private:
std::map<pricing_model::Operation,double> map_;
};
inline double& pricing_model::result_set::operator[](Operation op)
{
return map_[op];
}
This causes heap corruption. In debug, steeping over "delete rs", you can
see the callstack below:

2)
* const black_scholes_merton<european_put>& bsmep =
black_scholes_merton<european_put>::getModel();
* pricing_model::result_set* rs = new pricing_model::result_set;
* (*rs)[PRICE] = 77.0;
* double pr = (*rs)[pricing_model::PRICE];
* delete rs;

works fine. I just replaced the call to allOrSome by its one line.


Note, allOrSome is defined in another translation unit, in a DLL. The class
containing the method is exported.

I didn't define constructors/destructors for result_set because I think the
default ones generated by the compiler should be ok?

Any help is appreciated,

Regards,

PS: I link my main.exe and my dll against MS multithreaded runtime static
lib (not dll)
---------------------------------------------------------------------------------------------------------------------
ntdll.dll!0000000077ef2aa0()
[Frames below may be incorrect and/or missing, no symbols loaded for
ntdll.dll]
ntdll.dll!0000000077f623b1()
ntdll.dll!0000000077f11fbf()
kernel32.dll!0000000077d8fbaa()
> main.exe!_CrtIsValidHeapPointer(const void * pUserData=0x0000000000576b30)
> Line 2072 C++
main.exe!_free_dbg_nolock(void * pUserData=0x0000000000576b30, int
nBlockUse=1) Line 1279 + 0xa bytes C++
main.exe!_free_dbg(void * pUserData=0x0000000000576b30, int nBlockUse=1)
Line 1220 + 0xe bytes C++
main.exe!operator delete(void * pUserData=0x0000000000576b30) Line 54 +
0x12 bytes C++
main.exe!Operation, double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false>
>::_Node>::deallocate(std::_Tree_nod<std::_Tmap_traits<blitzq::pricing_model::Operation,
double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false> >::_Node * _Ptr=0x0000000000576b30,
std::allocator<std::_Tree_nod<std::_Tmap_traits<blitzq::pricing_model::Operation,
double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false> >::_Node> * this=0x0000000000584000) Line 142 C++
main.exe!Operation, double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false>
>::_Erase(std::_Tree_nod<std::_Tmap_traits<blitzq::pricing_model::Operation,
double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false> >::_Node * _Rootnode=0x0000000000576b30) Line 1073 C++
main.exe!Operation, double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false> >::clear() Line 955 C++
main.exe!Operation, double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false>
>::erase(std::_Tree<std::_Tmap_traits<blitzq::pricing_model::Operation,
double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false> >::iterator & _First=(PRICE,77.000000000000000),
std::_Tree<std::_Tmap_traits<blitzq::pricing_model::Operation, double,
std::less<blitzq::pricing_model::Operation>, std::allocator<std::pair<const
blitzq::pricing_model::Operation, double> >, false> >::iterator &
_Last=(-842150451,-6.2774385622041925e+066),
std::_Tree<std::_Tmap_traits<blitzq::pricing_model::Operation, double,
std::less<blitzq::pricing_model::Operation>, std::allocator<std::pair<const
blitzq::pricing_model::Operation, double> >, false> > *
this=0x0000000000583ff0) Line 921 C++
main.exe!Operation, double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false> >::_Tidy() Line 1327 + 0x4f bytes C++
main.exe!Operation, double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >,
false> >::~_Tree() Line 526 + 0xc bytes C++
main.exe!Operation, double, std::less<blitzq::pricing_model::Operation>,
std::allocator<std::pair<const blitzq::pricing_model::Operation, double> >
>::~map() + 0x22 bytes C++
main.exe!pricing_model::result_set::~result_set() + 0x22 bytes C++
main.exe!blitzq::pricing_model::result_set::`vector deleting destructor'()
+ 0x1e bytes C++
main.exe!main(int argc=7, char * * argv=0x0000000000584ae0) Line 60 C++

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Marsh Ray

unread,
Oct 7, 2008, 11:36:37 PM10/7/08
to
{ Further environment-specific discussions are better directed to
other appropriate groups. -mod }

On Oct 7, 2:59 pm, "Hicham Mouline" <hic...@mouline.org> wrote:
> PS: I link my main.exe and my dll against MS multithreaded runtime static
> lib (not dll)

Don't do that. Use the dynamically linked CRT.

>black_scholes_merton<european_put>
>allOrSome(result_set& res, const operation_set opset, const contract& c,
>const pricing_model_parameters& mparams) const
>{
>res[PRICE] = 77.0;

This is potentially making CRT allocations.

> Note, allOrSome is defined in another translation unit, in a DLL. The class

...


> main.exe!_free_dbg_nolock(void * pUserData=0x0000000000576b30, int
> nBlockUse=1) Line 1279 + 0xa bytes C++

You've got allocations made by one module (with it's own statically-
linked CRT) being freed by a different module (with a different static
copy of the CRT). This can cause problems.

Be very careful about passing STL containers across DLL boundaries.
Better not to do it at all. Even the tiniest differences in compiler
settings and preprocessor definitions can end up making the memory
layouts incompatible.

- Marsh

0 new messages