У меня странная ошибка доступа, которая возникает, только когда я запускаю программу вне IDE (я использую Code :: Block с компилятором GNU GCC и GBD в качестве отладчика).
Unhandled exception at 0x77cd82ea in SFinGe.exe: 0xC0000005: Access violation reading location 0x69687065.
Это происходит, когда я пытаюсь добавить элементы в std :: map. Я знаю, что это обычно происходит, когда у вас есть унифицированная переменная, но я тщательно изучал свой код и не могу найти проблему, и она сводит меня с ума.
Это определение класса:
//==============================================================================
// CDirectionalMapGenerator prototypes.
//==============================================================================
#ifndef CDIRECTIONALMAPGENERATOR_H
#define CDIRECTIONALMAPGENERATOR_H
//==============================================================================
#include <complex.h>
#include <math.h>
#include <map>
#include <vector>
#include <CRandom.h>
#include <SFingerprintPattern.h>
#include <ESingularityType.h>
//==============================================================================
#define PI 3.14159265359
//==============================================================================
/** \brief
* Generates a directional map using the orientation model proposed by Sherlock and Monro, this allows a consistent orientation image to be computed from
* the knowledge of the position of the fingerprint singularities (core and deltas) alone. The image is located in the complex plane and the local ridge
* orientation is the phase of the square root of a complex rational function whose singularities (poles and zeros) are located at the same place
* as the fingerprint singularities.
*/
class CDirectionalMapGenerator
{
public:
/** \brief
* Initializes a new instance of the CDirectionalMapGenerator class.
*
*/
CDirectionalMapGenerator();
/** \brief
* Destroy the CDirectionalMapGenerator object and all its reference safely.
*/
virtual ~CDirectionalMapGenerator();
/** \brief
* Generates a directional map.
* \param pattern CFingerprintPattern The fingerprint class and singularity types information.
* \param witdh int The witdh of the map.
* \param height int The height of the map.
* \return std::vector<std::vector<double>> The directional map.
*/
std::vector<std::vector<double> > generate(SFingerprintPattern& pattern, int width, int height);
private:
/** \brief
* Gets the segment orientation.
* \param z complex The complex number representing a point in the directional map.
* \return double The segment orientation in radians.
*/
double getSegmentOrientation(std::complex<double> z);
/** \brief
* Vizcaya and Gerhardt correction.
* \param alpha double The angle to be corrected.
* \param singularityType ESingularityType The singularity type.
* \return double The angle corrected.
*/
double correctOrientation(double alpha, ESingularityType singularityType);
/** \brief
* Gets the amount of angle correction for the given point. The directional map is uniformly divided between -PI and PI
* in eight segments (45 degrees each segment), points in each region must be adjusted using a different piecewise linear function.
* The variables 'v' and 'u' are angles defined at the beginning of the generation process, this angles are chosen depending on the
* singularity type and fingerprint class.
* \param q int Region of the point.
* \param singularityType ESingularityType The singularity type.
* \return double The amount of correction.
*/
double getAmountOfCorrection(int q, ESingularityType singularityType);
/** \brief
* Modification angles must be defined on the basis of position and number of singularities.
* \return void
*
*/
void generateWeigths();
private:
static CRandom* m_sRandom;
std::map<ESingularityType, double> m_v;
std::map<ESingularityType, double> m_u;
EFingerprintClass m_currentFingerprintClass;
SFingerprintPattern m_currentPattern;
double m_nArchTypeFactors[3];
int m_nCurrentWidth;
int m_nCurrentHeight;
};#endif // CDIRECTIONALMAPGENERATOR_H
и реализация:
#include "CDirectionalMapGenerator.h"//==============================================================================
// Static variable initialization.
CRandom* CDirectionalMapGenerator::m_sRandom = new CRandom(time(0));
//==============================================================================
CDirectionalMapGenerator::CDirectionalMapGenerator()
{
m_currentFingerprintClass = ARCH;
m_nCurrentWidth = 0;
m_nCurrentHeight = 0;
m_v = std::map<ESingularityType, double>();
m_u = std::map<ESingularityType, double>();
}
//==============================================================================
CDirectionalMapGenerator::~CDirectionalMapGenerator()
{
delete m_sRandom;
m_u.clear();
m_v.clear();
}
//==============================================================================
std::vector<std::vector<double> > CDirectionalMapGenerator::generate(SFingerprintPattern& pattern, int width, int height)
{
std::vector<std::vector<double> > directionalMap;
m_currentFingerprintClass = pattern.FingerprintClass;
m_currentPattern = pattern;
m_nCurrentWidth = width;
m_nCurrentHeight = height;
// Clear weights from last generation.
m_u.clear();
m_v.clear();
this->generateWeigths();
for (int i = 0; i < m_nCurrentWidth; ++i)
{
std::vector<double> vLine;
for (int j = 0; j < m_nCurrentHeight; ++j)
{
std::complex<double> z(i, j);
vLine.push_back(this->getSegmentOrientation(z));
}
directionalMap.push_back(vLine);
}
return directionalMap;
}//==============================================================================
double CDirectionalMapGenerator::getSegmentOrientation(std::complex<double> z)
{
double segmentOrientation = 0;
int degrees = 0;
if (m_currentFingerprintClass == ARCH)
{
// Arch patterns that do not contain any singularity are not supported by the model, a sinusoidal function
// must be use instead (The frequency and amplitude are tuned to control the arch curvature and aspect).
segmentOrientation = atan(std::max(0.0, (m_nArchTypeFactors[2] - m_nArchTypeFactors[2] * z.imag() / (m_nCurrentHeight * m_nArchTypeFactors[1]))) * cos(z.real() * PI / (m_nCurrentWidth * m_nArchTypeFactors[0])));
}
else if (m_currentFingerprintClass == WHORL)
{
// Whorl have two cores and two deltas.
// 1/2(g(arg(z - d1)) - g(arg(z - l1))) + 1/2(g(arg(z - d2)) - g(arg (z - l2)))
segmentOrientation = (0.5 * (this->correctOrientation(arg((z - m_currentPattern.DeltaOne)), DELTA) - this->correctOrientation(arg((z - m_currentPattern.LoopOne)), CORE))) +
(0.5 * (this->correctOrientation(arg((z - m_currentPattern.DeltaTwo)), SECONDARY_DELTA) - this->correctOrientation(arg((z - m_currentPattern.LoopTwo)), SECONDARY_CORE)));
}
else
{
// 1/2(g(arg(z - d)) - g(arg (z - l)))
segmentOrientation = 0.5 * (this->correctOrientation(arg((z - m_currentPattern.DeltaOne)), DELTA) - this->correctOrientation(arg((z - m_currentPattern.LoopOne)), CORE));
}
degrees = static_cast<int>(segmentOrientation * (180 / PI)); // From radiants to degrees.
if(degrees < 0)
degrees = -(((-1) * degrees) % (180)) + 180;
segmentOrientation = degrees * (PI / 180); // From degrees to radiants.
return segmentOrientation;
}
//==============================================================================
double CDirectionalMapGenerator::correctOrientation(double alpha, ESingularityType singularityType)
{
int q = static_cast<int>(floor(4 * (PI + alpha) / PI));
double alphaI = -PI + (PI * q) / 4;
double correctionOne = this->getAmountOfCorrection(q + 1, singularityType); //gk(alpha i)
double correctionTwo = this->getAmountOfCorrection(q + 2, singularityType); //gk(alpha i + 1)
return (correctionOne + ((4 * (alpha - alphaI)) / PI) * (correctionTwo - correctionOne));
}
//==============================================================================
double CDirectionalMapGenerator::getAmountOfCorrection(int q, ESingularityType singularityType)
{
double amountOfCorrection = 0;
switch (q)
{
case 1:
amountOfCorrection = -PI + m_u[singularityType];
break;
case 2:
amountOfCorrection = -3 * PI / 4 + m_u[singularityType];
break;
case 3:
amountOfCorrection = -PI / 2;
break;
case 4:
amountOfCorrection = -PI / 4 + m_v[singularityType];
break;
case 5:
amountOfCorrection = m_v[singularityType];
break;
case 6:
amountOfCorrection = PI / 4 + m_v[singularityType];
break;
case 7:
amountOfCorrection = PI / 2;
break;
case 8:
amountOfCorrection = 3 * PI / 4 + m_u[singularityType];
break;
default:
amountOfCorrection = PI + m_u[singularityType];
break;
}
return amountOfCorrection;
}
//==============================================================================
void CDirectionalMapGenerator::generateWeigths()
{
switch (m_currentFingerprintClass)
{
case(ARCH):
m_nArchTypeFactors[0] = (0.8 + 0.4 * m_sRandom->nextDouble());
m_nArchTypeFactors[1] = (0.6 + 0.8 * m_sRandom->nextDouble());
m_nArchTypeFactors[2] = (1.2 + m_sRandom->nextDouble() * 1.5);
break;
case (LEFT_LOOP):
m_u[CORE] = -120 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
m_v[CORE] = 50 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
break;
case (RIGHT_LOOP):
m_u[CORE] = -90 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
m_v[CORE] = 60 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
break;
case (TENTED_ARCH):
m_u[CORE] = -90 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
m_v[CORE] = 45 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
break;
case (WHORL):
// Whorl have two cores and two deltas.
m_u[CORE] = -60 * PI / 180.0 + m_sRandom->nextDouble() * (15 * PI / 180.0);
m_v[CORE] = 40 * PI / 180.0 + m_sRandom->nextDouble() * (15 * PI / 180.0);
m_u[SECONDARY_CORE] = 10 * PI / 180.0 + m_sRandom->nextDouble() * (15 * PI / 180.0);
m_v[SECONDARY_CORE] = 20 * PI / 180.0 + m_sRandom->nextDouble() * (15 * PI / 180.0);
break;
}
m_u[DELTA] = 0;
m_v[DELTA] = 0;
m_u[SECONDARY_DELTA] = 0;
m_v[SECONDARY_DELTA] = 0;
}
Это метод, который ломает:
void CDirectionalMapGenerator::generateWeigths()
{
switch (m_currentFingerprintClass)
{
case(ARCH):
m_nArchTypeFactors[0] = (0.8 + 0.4 * m_sRandom->nextDouble());
m_nArchTypeFactors[1] = (0.6 + 0.8 * m_sRandom->nextDouble());
m_nArchTypeFactors[2] = (1.2 + m_sRandom->nextDouble() * 1.5);
break;
case (LEFT_LOOP):
m_u[CORE] = -120 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
m_v[CORE] = 50 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
break;
case (RIGHT_LOOP):
m_u[CORE] = -90 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
m_v[CORE] = 60 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
break;
case (TENTED_ARCH):
m_u[CORE] = -90 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
m_v[CORE] = 45 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
break;
case (WHORL):
// Whorl have two cores and two deltas.
m_u[CORE] = -60 * PI / 180.0 + m_sRandom->nextDouble() * (15 * PI / 180.0);
m_v[CORE] = 40 * PI / 180.0 + m_sRandom->nextDouble() * (15 * PI / 180.0);
m_u[SECONDARY_CORE] = 10 * PI / 180.0 + m_sRandom->nextDouble() * (15 * PI / 180.0);
m_v[SECONDARY_CORE] = 20 * PI / 180.0 + m_sRandom->nextDouble() * (15 * PI / 180.0);
break;
}
m_u[DELTA] = 0;
m_v[DELTA] = 0;
m_u[SECONDARY_DELTA] = 0;
m_v[SECONDARY_DELTA] = 0;
}
Всякий раз, когда я пытаюсь присвоить значение карте, она дует:
m_u[CORE] = -90 * PI / 180.0 + m_sRandom->nextDouble() * (45 * PI / 180.0);
Я не уверен, в чем дело, я инициализировал все члены, которые нуждаются в этом в конструкторе, все остальные передаются в качестве параметров в метод «генерировать».
Чего мне не хватает?
Вы используете два CDirectionalMapGenerator
в вашей программе? Ваша статическая переменная m_sRandom
только new
один раз в начале программы, но delete
д всякий раз, когда CDirectionalMapGenerator
уничтожен Если вы создаете второй CDirectionalMapGenerator
после того, как первый уничтожен, всякий раз, когда он получает доступ m_sRandom
вы будете разыменовывать неверный указатель.
Либо убедитесь, что вы не delete
m_sRandom
указатель до конца вашей программы или сделать его нестатичным, чтобы каждый экземпляр CDirectionalMapGenerator
имеет свою копию.
Других решений пока нет …