我正在调试某人的代码而我收到错误:这可能是由于堆的损坏,这表明.exe或其加载的任何DLL中存在错误。我研究并了解到这是由于一些内存泄漏,对象没有从堆中正确删除。我查看并查看了代码(逐行调试),并在return语句中崩溃。这是代码:问题出在哪里?
首先调用DLL的c#代码
public class Analysis
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1), Serializable]
public struct Pothole
{
public int Id;
public int FrameNumber;
public int LeftX;
public int TopY;
public int Width;
public int Height;
public int Certainty; // note that this is a percentage value, hence integer
public double Latitude;
public double Longitude;
public double Speed;
public double Area;
public double Volume;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 20)]
public string TimeCreated;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 200)]
public string CroppedImage;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 200)]
public string LeftImage;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 200)]
public string RightImage;
};
private int progress;
public int Progress
{
get { return progress; }
set { progress = value; }
}
public List<FileInfo> AllVideoFiles;
public List<FileInfo> FramesInDir;
public List<GpsPoint> GpsList;
public VideoMetaData MetaData;
public List<TrackPothole> PotholeList;
public VideoHandling VideoHandler;
public int verbose; //if verbose, then you get a lot of wordy output on what the program is doing
private VspDatabaseEntities1 _vde;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void ProgressCallback(int value);
public event ProgressCallback OnProgressUpdated;
//initializes video files and calibraiton file names
[DllImport(@"Analyser.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int Initialize(string SettingsDir, int SettingDirLength, string LeftVideoFile, int LeftFileLength,
string RightVideoFile, int RightFileLength, string GpsCoordsFile, int GpsFileLength, string OutputDirectory, int OutputDirLength);
//analyse road files (do everything)
[DllImport(@"Analyser.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int Start([MarshalAs(UnmanagedType.FunctionPtr)] ProgressCallback callbackPointer, int verbose);
//Does the analysis of videos, uses the c++ analysis Start() function
public void Go(ProgressBar bar)
{
//flag -> should actually be set outside of function, can't find the outside
verbose = 1;
//obtain parameters from settings.settings
string inputDir = Properties.Settings.Default["InputDir"].ToString();
string outputDir = Properties.Settings.Default["OutputDir"].ToString();
string settingsDir = Properties.Settings.Default["SettingsDir"].ToString();
//setup directories and filenames
//string camfile = settingsDir + "\\" + "Calib.yaml"; => now we send the directory, not the specific file
string rightvid = "";
string leftvid = "";
string gpsfile = "";
//Associate multiple files according to creation times and loop through matching pairs
//(this works because of the copy operation? -> but won't everything have the same time then?)
AllVideoFiles = GetFiles(inputDir, "*.avi");
List<FileInfo> rightvids = new List<FileInfo>(AllVideoFiles.Where(v => v.FullName.Contains("3D_R")).OrderBy(v => v.CreationTime));
List<FileInfo> leftvids = new List<FileInfo>(AllVideoFiles.Where(v => v.FullName.Contains("3D_L")).OrderBy(v => v.CreationTime));
List<FileInfo> gpsfiles = new List<FileInfo>(GetFiles(inputDir, "*.txt").OrderBy(g => g.CreationTime));
Console.WriteLine("Got this far1");
//Check that the number of right and left video files and gps files match
int lowestCount = 0;
if (rightvids.Count != leftvids.Count)
{
MessageBox.Show("Error: The number of right camera videos does not match the number of left camera videos!");
if (rightvids.Count < leftvids.Count)
lowestCount = rightvids.Count;
else
lowestCount = leftvids.Count;
}
else
lowestCount = rightvids.Count;
if (gpsfiles.Count != lowestCount)
{
MessageBox.Show("Error: The number of gps data files does not match the number of right camera video files!");
if (gpsfiles.Count < lowestCount)
lowestCount = gpsfiles.Count;
}
//@todo
//Currently, looping through the files and hoping there is only one in the file.
Console.WriteLine("Got this far2");
for (int i = 0; i < lowestCount; i++)
{
rightvid = rightvids[i].FullName;
leftvid = leftvids[i].FullName;
gpsfile = gpsfiles[i].FullName;
if (verbose==1)
Console.WriteLine("C# FileNames: " + settingsDir + " " + outputDir + " " + leftvid + " " + gpsfile);
//Pass the filenames to the c++ functions
int InitReturn = Initialize(settingsDir, settingsDir.Length, leftvid, leftvid.Length,
rightvid, rightvid.Length, gpsfile, gpsfile.Length, outputDir, outputDir.Length);
if (verbose == 1)
{
Console.WriteLine("Initilize return value : " + InitReturn);
Report();
}
//Setup the progress bar
ProgressCallback callback = (value) => bar.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(delegate() {bar.Value = value;} ));
//***RUN THE ANALYSIS
Console.WriteLine("Got this far4");
int start_ret_val = Start(callback, verbose);
if (verbose==1) Console.WriteLine("Start return value: " + start_ret_val);
//Create the pothole array
Pothole[] potArr = new Pothole[10000];
Thread.Sleep(1000); //@todo Why sleep?
if (start_ret_val > 0)
{
//fill up the array
///@todo How does this impact the memory wastage?
potArr = GetPotholes(start_ret_val);
MessageBox.Show("Analysis completed");
//bar.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
// new Action( delegate() { bar.Value = 0; } ));
}
else
{
MessageBox.Show("Analysis returned with error code : " + start_ret_val); //@todo Add some interpretation here
}
Console.WriteLine("Got this far5");
}
}
}
C ++函数从这里开始:
cv::Mat RunClassifier(cv::Mat& frame, cv::Mat& mask, std::vector<CvANN_MLP*>& anns, std::vector<int>& criteria,std::vector<float>& thresholds, Mat& final_certainty)
{
//instantiate certainty matrix
std::vector<Mat> indiv_certs;
for (unsigned int i = 0; i < anns.size(); i++)
indiv_certs.push_back(Mat::zeros(frame.size(), CV_32FC1) );
Mat certainty = Mat::zeros(frame.size(), CV_32FC1);
final_certainty = Mat::zeros(frame.size(), CV_32FC1);
Mat final_image = frame.clone();
Mat* individual_masks = new Mat[anns.size()]();
for (unsigned int iter = 0; iter < anns.size();iter++)
{
individual_masks[iter] = Mat::zeros(frame.rows,frame.cols,CV_32F);
}
Mat final_mask = Mat::zeros(frame.rows,frame.cols,CV_32F);
//Convert the image to HSV colorspace (You could probably save a bit more if you converted and normalised the frame to 32F beforehand
// and not individually for each channel.
Mat hsv;
std::vector<Mat> hsv_channels;
cvtColor(frame, hsv, CV_BGR2HSV);
split(hsv, hsv_channels);
Mat hue, value, saturation;
hsv_channels.at(HUE).convertTo(hue, CV_32F);
hue /= HUE_MAX;
hue = 1- hue;
hsv_channels.at(SATURATION).convertTo(saturation, CV_32F);
Mat sat_pure = saturation.clone();
saturation /= SATURATION_MAX;
hsv_channels.at(VALUE).convertTo(value, CV_32F);
value /= VALUE_MAX;
//loop through the anns
//Declare multithreading variables
PCERT_DATA pCert_Array[3];
DWORD dwThreadIdArray[3];
HANDLE hThreadArray[3];
for (unsigned int ann_iter = 0; ann_iter < anns.size(); ann_iter++)
{
//allocate memory for thread data
pCert_Array[ann_iter] = (PCERT_DATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CERT_DATA) );
bool fft_flag = FALSE;
//Convert the image block according to the ann
switch (criteria.at(ann_iter))
{
case HUE:
{
pCert_Array[ann_iter]->converted_frame = &hue;
break;
}
case SATURATION:
{
pCert_Array[ann_iter]->converted_frame = &saturation;
break;
}
case VALUE:
{
pCert_Array[ann_iter]->converted_frame = &value;;
break;
}
case FREQUENCY:
{
pCert_Array[ann_iter]->converted_frame = &sat_pure;
fft_flag = TRUE;
break;
}
default:
{
return Mat();
}
}
//assign data to memory
pCert_Array[ann_iter]->ann = anns.at(ann_iter);
pCert_Array[ann_iter]->certainty = &(indiv_certs[ann_iter]);
pCert_Array[ann_iter]->mask = &mask;
pCert_Array[ann_iter]->fft_flag = fft_flag;
pCert_Array[ann_iter]->individual_mask = &(individual_masks[ann_iter]);
pCert_Array[ann_iter]->threshold = thresholds.at(ann_iter);
//call CalculateCertainty
hThreadArray[ann_iter] = CreateThread(
NULL, // default security attributes
0, // use default stack size
ComputeCertainty, // thread function name
pCert_Array[ann_iter], // argument to thread function
0, // use default creation flags
&dwThreadIdArray[ann_iter]); // returns the thread identifier
}
//wait for all the threads to stop computing
WaitForMultipleObjects(anns.size(), hThreadArray, TRUE, INFINITE);
//summing operation of certanties
for (unsigned int i = 0; i < anns.size(); i++)
certainty += indiv_certs[i];
//AND all the various ANN outputs
Mat temp = Mat::zeros(individual_masks[0].size(), individual_masks[0].type() );
for (unsigned int i = 0; i < anns.size(); i++)
temp += individual_masks[i];
Mat temp_binary_mask = (temp == anns.size());
temp = Mat::ones(individual_masks[0].size(), individual_masks[0].type() );
temp.copyTo(final_mask, temp_binary_mask);
cv::multiply(final_mask, certainty, final_certainty, 1.0/anns.size() );
delete individual_masks;
//deallocate threading memory used
for(unsigned int i=0; i<anns.size(); i++)
{
CloseHandle(hThreadArray[i]);
if(pCert_Array[i] != NULL)
{
HeapFree(GetProcessHeap(), 0, pCert_Array[i]);
pCert_Array[i] = NULL; // Ensure address is not reused.
}
}
return final_mask;
}
答案 0 :(得分:3)
您是否尝试使用内存泄漏检测工具,例如Visual Leak Detector?
在下面的代码中,
Mat* individual_masks = new Mat[anns.size()]();
operator delete[]
删除,以便delete[] individual_masks;
此外,无论内存泄漏,都应该进行数组边界检查。
for (unsigned int ann_iter = 0; ann_iter < anns.size(); ann_iter++)
{
//allocate memory for thread data
pCert_Array[ann_iter] = (PCERT_DATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CERT_DATA) );
anns
是输入参数,因此它的大小不是固定值,但在pCert_Array
中声明PCERT_DATA pCert_Array[3];
。