【发布时间】:2015-08-06 03:13:47
【问题描述】:
我有:
- 非托管 C++ 应用程序
- C++/CLI 包装器
- 一个 C# 图形用户界面
我看到这个崩溃只发生在发布而不是调试中。当非托管 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::allocator
- __ptr64,std::basic_string,std::allocator
(std::basic_string,std::allocator > * _First, std::basic_string,std::allocator > * _Last, const std::basic_string,std::allocator > & _Val) 第 41 行 + 0x4a 字节 C++ DataVerifier.exe!DataVerifier::CPCAPParser::Parse(const char * szFileName, 标准::向量 & vSFramesRWF1Messages, std::vector,std::allocator ,std::allocator,std::allocator
- vstrEEDRRMachines、std::vector、std::allocator ,std::allocator,std::allocator
- vstrRRRHMachines, RsslDataDictionary & rsslDataDictionary) 第 178 行 + 0x19 字节 C++ [外部代码]
DataVerifierLib.dll!DataVerifierLib::PCAPParserWrapper::ParseWrapper(System::String^ strInputFileNames) 第 136 行 + 0xf6 字节 C++ DataVerifierGUI.exe!DataVerifierGUI.Form1.button1_Click(object 发件人,System.EventArgs e) 第 42 行 + 0x30 字节 C# user32.dll!00007fff7a8c250d() user32.dll!00007fff7a8c2367()
System.Windows.Forms.ni.dll!00007fff535368c0()
崩溃具体发生在c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm这部分代码中:
// 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++
};
}
【问题讨论】:
-
我们无法告诉您如何修复我们看不到的代码。根据堆栈跟踪,问题出在上面的
CPCAPParser::Parse和PCAPParserWrapper::ParseWrapper,所以你应该开始寻找那里。 -
我上面写的IF语句是在CPCAPParser的Parse函数中,所以我粘贴了它。我很好奇是否有人知道它为什么会在那条线上崩溃以及为什么特别是在那个算法类中。可能与发布和调试之间的堆栈分配有关吗?
-
您是否尝试调试发布版本?你可以关闭优化设置试试看。
-
是的,那一小段代码并没有告诉我们什么是引用,什么不是,它没有告诉我们类型,它没有向我们显示调用的代码它或已在整个调用链中进行了适当的验证。最少代码是一回事,代码不足是另一回事。这些变量中的任何一个都可能是您未定义行为的原因。
-
我猜我在变量中看到了奇怪的值,因为我已经开启了优化(?)我没有检查我不在电脑 ATM 上。如何关闭优化并尝试调试发布模式,就像使用调试模式一样?
标签: c# visual-c++ stl c++-cli clr