0xC0000005:访问冲突读取位置0xffffffffffffffff

本文关键字:位置 0xffffffffffffffff 读取 访问冲突 0xC0000005 | 更新日期: 2023-09-27 18:06:31

我有:

  • 一个非托管的c++应用程序
  • c++/CLI包装器
  • c# gui

我看到这个崩溃只发生在发布而不是调试。当非托管c++应用程序自己运行时,在调试或发布时也不会发生崩溃。

我只能说崩溃发生在这行代码中:

            if ((std::find(vstrEEDRRMachines.begin(), vstrEEDRRMachines.end(), m_sFrame.strSourceAddress) != vstrEEDRRMachines.end()
                && std::find(vstrEEDRRMachines.begin(), vstrEEDRRMachines.end(), m_sFrame.strDestAddress) != vstrEEDRRMachines.end())
                || (std::find(vstrRRRHMachines.begin(), vstrRRRHMachines.end(), m_sFrame.strSourceAddress) != vstrRRRHMachines.end()
                && std::find(vstrRRRHMachines.begin(), vstrRRRHMachines.end(), m_sFrame.strDestAddress) != vstrRRRHMachines.end())) 
            {
                // Create appropriate buffer size for raw message (i.e. size of payload along with the extra padding
                // for decoding)
                m_sFrame.iMessageSize = m_sFrame.iPayloadLength;
                m_sFrame.iOriginalMessageSize = m_sFrame.iPayloadLength;
                m_sFrame.pszMessage = new unsigned char[m_sFrame.iPayloadLength + Constants::RSSL_DECODE_PADDING];
                m_sFrame.pszOriginalMessage = new unsigned char[m_sFrame.iPayloadLength + Constants::RSSL_DECODE_PADDING];
            }

虽然我不能看到vstrEEDRRMachines和vstrRRRHMachines里面有什么(因为我们还在发布中),但我可以看到在原始的c++/CLI包装器中,向量中有有效的字符串条目。

堆栈跟踪如下:

msvcr100.dll!0000000069abbdc0()[以下帧可能不正确。和/或缺少,没有符号加载msvcr100.dll]
DataVerifier.exe !std:: _Find, std::分配器

  • __ptr64, std:: basic_string, std::分配器

    (std::basic_string,std::allocator> * _First, std::basic_string,std::allocator> * .std::basic_string,std::allocator> &第41行+ 0x4a字节c++DataVerifier.exe !DataVerifier::CPCAPParser::Parse(const char * szFileName,std::向量,vSFramesRWF1Messages, std::向量,std::分配器std::分配器,std::分配器

    • vstrEEDRRMachines, std::向量,std::分配器std::分配器,std::分配器
    • vstrRRRHMachines, RsslDataDictionary &第178行+ 0x19字节c++[外部代码]
      DataVerifierLib.dll !DataVerifierLib: PCAPParserWrapper:: ParseWrapper(系统::字符串^第136行+ 0xf6字节c++DataVerifierGUI.exe ! DataVerifierGUI.Form1.button1_Click(对象发送者,系统。e)第42行+ 0x30字节c#user32.dll ! 00007 fff7a8c250d () user32.dll ! 00007 fff7a8c2367 ()
      System.Windows.Forms.ni.dll ! 00007 fff535368c0 ()

崩溃特别发生在c:'Program Files (x86)'Microsoft Visual Studio 10.0'VC'include'算法中的这部分代码:

        // TEMPLATE FUNCTION find
template<class _InIt,
    class _Ty> inline
    _InIt _Find(_InIt _First, _InIt _Last, const _Ty& _Val)
    {   // find first matching _Val
    for (; _First != _Last; ++_First)
        if (*_First == _Val) <-- CRASH OCCURS HERE
            break;
    return (_First);
    }

我不知道发生了什么,因为c# + c++/CLI + c++应用程序的发布模式是发生崩溃的地方。有什么办法能让我轻松解决这个问题吗?

编辑

似乎这发生了10次中的9次,但我注意到它确实起作用的时候,当我检查Parse函数的参数时,就像它进入函数一样(还没有执行行),所有3个向量都有正常值(第一个是0,第二个和第三个包含IP地址如预期的那样)。然而,大多数时候,只要我们进入Parse函数,所有3个向量的大小和容量都是负的……当它们被使用时,一切都爆炸了。我将跳过Parse函数的入口,以及它之前的c++/CLI包装器。

bool CPCAPParser::Parse(const char* szFileName, std::vector<CRWFCapsule> &vSFramesRWF1Messages, std::vector<std::string> vstrEEDRRMachines, std::vector<std::string> vstrRRRHMachines, RsslDataDictionary &rsslDataDictionary) // change to a vector of rwf1capsules
{

这是c++/CLI包装器:

// This is the main DLL file.
#include "stdafx.h"
#include "DataVerifierLib.h"
// Constructor Implementation
DataVerifierLib::PCAPParserWrapper::PCAPParserWrapper()
{
}
std::vector<std::string> DataVerifierLib::PCAPParserWrapper::CreateNewMachineCollection(std::vector<std::string> vstrNewMachines, std::vector<std::string> vstrMachine1, std::vector<std::string> vstrMachine2)
{
    vstrNewMachines.reserve(vstrMachine1.size() + vstrMachine2.size()); // preallocate memory
    vstrNewMachines.insert(vstrNewMachines.end(), vstrMachine1.begin(), vstrMachine1.end());
    vstrNewMachines.insert(vstrNewMachines.end(), vstrMachine2.begin(), vstrMachine2.end());
    return vstrNewMachines;
}
bool DataVerifierLib::PCAPParserWrapper::ParseWrapper(String^ managedString)
{
    // String conversion from c# to c++
    String^ managedStringTmp = managedString;
    std::string strInputFileNames = msclr::interop::marshal_as<std::string>(managedStringTmp);
    std::vector<std::string> vRRMachines;
    std::vector<std::string> vRHMachines;
    std::vector<std::string> vEEDMachines;
    std::vector<std::string> vPorts; // decide on what checks are to be made. Should frame have matching src/dest ports? or just one of them.
    std::vector<std::string> vEEDRRMachines;
    std::vector<std::string> vRRRHMachines;
    std::vector<std::string> vstrLines;
    std::string strTxtFile = "ServerIPList.txt"; //argv[2]; // ServerIPList.txt
    std::string strLine;
    std::ifstream in(strTxtFile);
    if (!in)
    {
        std::cout << "There was a problem opening the file." << std::endl;
        std::cerr << "Error: " << strerror(errno) << std::endl;
        return -1;
    }
    while (std::getline(in, strLine))
    {
        vstrLines.push_back(strLine);
    }
    for (int i = 0; i < vstrLines.size(); ++i)
    {
        if (vstrLines[i].substr(0, 2) == "rr")
        {
            boost::split(vRRMachines, vstrLines[i], boost::is_any_of(","));
            if (vRRMachines.size() < 2)
                return -1;
            else
                vRRMachines.erase(vRRMachines.begin());
        }
        else if (vstrLines[i].substr(0, 2) == "rh")
        {
            boost::split(vRHMachines, vstrLines[i], boost::is_any_of(","));
            if (vRHMachines.size() < 2)
                return -1;
            else
                vRHMachines.erase(vRHMachines.begin());
        }
        else if (vstrLines[i].substr(0, 3) == "eed")
        {
            boost::split(vEEDMachines, vstrLines[i], boost::is_any_of(","));
            if (vEEDMachines.size() < 2)
                return -1;
            else
                vEEDMachines.erase(vEEDMachines.begin());
        }
        else if (vstrLines[i].substr(0, 5) == "ports")
        {
            boost::split(vPorts, vstrLines[i], boost::is_any_of(","));
            if (vPorts.size() < 2)
                return -1;
            else
                vPorts.erase(vPorts.begin());
        }
    }
    // Create a vector with EED/RR and RR/RH combined addresses
    vEEDRRMachines = CreateNewMachineCollection(vEEDRRMachines, vEEDMachines, vRRMachines);
    vRRRHMachines = CreateNewMachineCollection(vRRRHMachines, vRRMachines, vRHMachines);
    // Initialise Rssl
    RsslRet rsslRet;
    RsslError rsslError;
    rsslRet = rsslInitialize(RSSL_LOCK_NONE, &rsslError);
    if (rsslRet != RSSL_RET_SUCCESS)
        return -1;
    // Initialise Field Dictionary
    // To prevent memory issues, we need to use "malloc" for the data dictionary in order to load RWF.dat and enumtype.def
    RsslDataDictionary *rsslDataDictionary = (RsslDataDictionary*)malloc(sizeof(RsslDataDictionary));
    RsslBuffer rsslBufferError;
    rsslClearDataDictionary(rsslDataDictionary);
    if (rsslRet = rsslLoadFieldDictionary("RWF.DAT", rsslDataDictionary, &rsslBufferError) != RSSL_RET_SUCCESS)
    {
        // Ensure we free the data dictionary memory when finished
        free(rsslDataDictionary);
        //if (iDisplayType != DISPLAY)
        //  std::cout << "Could not load RDM Field Dictionary file." << std::endl;
        return -1;
    }
    // Load enum dictionary
    if (rsslLoadEnumTypeDictionary("enumtype.def", rsslDataDictionary, &rsslBufferError) != RSSL_RET_SUCCESS)
    {
        // Ensure we free the data dictionary memory when finished
        free(rsslDataDictionary);
        //if (iDisplayType != DISPLAY)
        //  std::cout << "Could not load Enum Type Dictionary file." << std::endl;
        return -1;
    }
    std::string strCombinedFileName;
    std::vector<CRWFCapsule> vRWFCapsules;
    std::vector<std::string> vstrInputFileNames;
    pPcapParser = new CPCAPParser(1,1); // Initiate C++ class instance
    boost::algorithm::split_regex(vstrInputFileNames, strInputFileNames, boost::regex(","));
    // Let's iterate through each PCAP file and parse it.
    for (int i = 0; i < vstrInputFileNames.size(); ++i)
    {
        if (false == strCombinedFileName.empty())
        {
            strCombinedFileName.append("-");
        }
        if (false == pPcapParser->Parse(vstrInputFileNames[i].c_str(), vRWFCapsules, vEEDRRMachines, vRRRHMachines, *rsslDataDictionary))
        {
            delete pPcapParser;
            // Ensure we free the data dictionary memory when finished
            free(rsslDataDictionary);
            vRWFCapsules.clear();
            return -1;
        }
        strCombinedFileName = strCombinedFileName.append(pPcapParser->GetFileName());
    }
    //if (iDisplayType != NO_DISPLAY)
    //  std::cout << "Clearing up..." << std::endl;
    delete pPcapParser;
    if (rsslRet = rsslDeleteDataDictionary(rsslDataDictionary) != RSSL_RET_SUCCESS)
    {
        // Ensure we free the data dictionary memory when finished
        free(rsslDataDictionary);
        //if (iDisplayType != NO_DISPLAY)
        //  std::cout << "Problem deleting dictionary." << std::endl;
        return -1;
    }
    // Ensure we free the data dictionary memory when finished
    free(rsslDataDictionary);
    if (vRWFCapsules.empty())
        return -1;
    CMessageSorter msgSorter(vEEDMachines, vRRMachines);
    std::map<std::string, SMessageInfo> m_msMessageInfo;
    std::map<std::string, SSystemInfo> m_msSystemInfo = msgSorter.SortMessages(vRWFCapsules, 1, m_msMessageInfo);
    if (m_msSystemInfo.empty())
        return -1;
    CDataVerifier dataVerifier(strCombinedFileName, 1, 1);
    dataVerifier.CreateOutputForAllMessages(m_msMessageInfo);
    dataVerifier.Process(m_msSystemInfo);
    // When clearing the vector, we have to make sure that the destructor of the RWF message is being called... so everything destroys itself correctly.
    // Will need to check if destruction is down properly. However, how can we delete RWF Capsules encapsulated in eachother?...
    vRWFCapsules.clear();
}

及其相应的头文件:

// DataVerifierLib.h
#pragma once
#include "../DataVerifier/CRWFCapsule.h"
#include "../DataVerifier/ISystem.h"
#include "../DataVerifier/CFrameAnalyser.h"
#include "../DataVerifier/CPCAPParser.h"
#include "../DataVerifier/CMessageSorter.h"
#include "../DataVerifier/CDataVerifier.h"
#include "../DataVerifier/CSourceDirectoryResponse.h"
#include "../DataVerifier/CDataVerifierConstants.h"
#include <vector>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <boost/algorithm/string.hpp>
#include <msclr/marshal_cppstd.h>
using namespace System;
using namespace DataVerifier;
namespace DataVerifierLib {
    public ref class PCAPParserWrapper
    {
        // TODO: Add your methods for this class here.
    public:
        // Constructor
        PCAPParserWrapper();
        // Wrapper Methods
        bool ParseWrapper(String^ strInputFileNames);
        // Fill vectors with appropriate RR/EED/RH addresses
        std::vector<std::string> CreateNewMachineCollection(std::vector<std::string> vstrNewMachines, std::vector<std::string> vstrMachine1, std::vector<std::string> vstrMachine2);
        // Public Variable
        double initVal;
    private:
        CPCAPParser *pPcapParser; // an instance of class in C++
    };
}

0xC0000005:访问冲突读取位置0xffffffffffffffff

我不知道为什么我收到了反对票,因为这个解决方案可能对那些混合使用c#和c++/CLI包装器的人非常有用。

我意识到可疑的行实际上是这一行:

//String^ managedStringTmp = managedString;
//std::string strInputFileNames = msclr::interop::marshal_as<std::string>(managedStringTmp);
std::string strInputFileNames = marshalString<E_UTF8>(managedString);

我显然已经改变了它,所以它正在使用这个新的"marshalString"函数。我从这里的链接中使用了一个封送字符串模板类,因为它似乎可以解决性能问题。

http://blog.nuclex-games.com/mono-dotnet/cxx-cli-string-marshaling/

现在我需要做的就是弄清楚为什么从包装器返回true并将其分配给c#中的布尔值返回false…但希望这能帮助一些人。

这解释了为什么在包装器中返回false或true不能工作,我们要么需要使用函数的封送(不想这样做),要么为false返回0,为true返回1。

c# DllImport与c++布尔函数不正确返回