Pergunta

There is a large legacy project I have to maintain, which I recently upgraded from Visual Studio 2008 to Visual Studio 2012. As it is a COM server and a OCX control, creating all the typelib stuff etc. resulted in some problems that I managed to solve. However, when I run the Release build now I frequently get crashes.

I followed some advise I found here on SO and was able to track down the crash to the following piece of code:

int Phx2Preview::ClearOvlElementList() {
    for (int i = 0; i < (int)m_vOvlElements.size(); i++) {
        P_SAFE_DELETE(m_vOvlElements[i].pPolyOrig);    // <- code crashes here
        P_SAFE_DELETE(m_vOvlElements[i].pPolyDispl);
    }
    m_vOvlElements.clear();
    m_vRefElemList.clear();
    m_pRefElemSelected = NULL;
    return PHXE_NO_ERROR;
}

P_SAFE_DELETE is a macro that checks if the pointer is null, and in case it's not deletes and sets it to null. The actual vector elements are created like this:

if (v1) {
    tNew.pPolyOrig = new CInPolygon();
    tNew.pPolyDispl = new CInPolygon();
    tNew.pPolyOrig->FromSafeArray(v1);
    tNew.pPolyOrig->Rotate(NULLPOINT, m_nTurnAngle*__pi/180.);
    tNew.eType = (overlayET)type;
    tNew.nImagenr = nImageNr;
    m_vOvlElements.push_back(tNew);
}

Now, the thing is that CInPolygon is a class from an external library which is created with Visual C++ 7.1. The P_SAFE_DELETE is also defined in a header from that library. From here I know that mixing different runtime versions is bad, and this question lets me suspect that this mixing may be responsible from the crash.

My question is: Why does it happen? After all, since both new and delete are called from the same place, no actual objects are passed between the different CRTs. Also, when the OCX is compiled using Visual Studio 2008, no problems occur. Is this due to pure luck? I guess the basic issue is existing in that setting, too. And, well, what can I do to solve to problem? Switch back to VS2008?


Edit:

As asked: The destructor of CInPolygon is just

CInPolygon::~CInPolygon(void) {
  m_vPoints.clear();
}

here the m_vPoints is a std::vector<..> defined in the class. Maybe I should mention that CInPolygon inherits from that:

interface IRoi {
  virtual ~IRoi() {
    return;
  }
public:
  // other stuff
};

(Didn't even know that interface was a valid keyword in plain C++...) Could it be that the fact that the base class destructor is defined in the header is causing the problem? After all, that header is also known to the host programm..

Foi útil?

Solução

  tNew.pPolyOrig = new CInPolygon();

Yes, this is guaranteed to fail. Short from having different allocators in your program, your host program cannot possibly compute the size of the CInPolygon object correctly. It uses an entirely different implementation of std::vector. It was significantly rewritten in VS2012 to take advantage of C++11. Inevitably, the code in the library using the old version of vector will corrupt the heap.

You must rebuild the library as well, using the exact same version of the compiler with the exact same settings.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top