цвета — в то время как цикл вызывает дамп стека и сбой программы в переполнении стека

Я только возвращаюсь к программированию на C ++. Я написал программу, которая должна считывать шестнадцатеричные цвета из файла, математически сравнивать их с массивом цветов, определенных в программе, чтобы определить, какой из них является наиболее близким, а затем записывать исходный цвет и ближайший цвет в файл. По какой-то причине после написания около 62 000 строк или около того программа завершает работу с дампом стека. Файл, из которого я читаю, содержит около 16 миллионов цветов. Я надеялся, что кто-нибудь сможет указать мне правильное направление с моим кодом, чтобы решить эту проблему.

Код ниже, я не вставлял массивы для красного, зеленого, синего или pantonehexcode; но вы можете предположить, что они являются массивом с числовыми и шестнадцатеричными значениями строки соответственно.

    string line;
string hexcolor, r_hex, g_hex, b_hex;

const char delim[] = " ;";
float *cie1 = new float[3];
float *cie2 = new float[3];

float r ;
float g ;
float b ;
float currentClosestVal = 1000000;
float challengeClosestVal;
int currentClosestIndex;

ifstream file ("hexcolormaplist.txt");
if (file.fail())
{cout << "Error opening infile file"; return 0;}
ofstream ofile("tpxmap.txt");
if (ofile.fail())
{cout << "Error opening ofile file"; return 0;}

bool newline = true;
//Comparing colors variables
int i, k;
double Kl, K1, K2, Sl, SC, SH, dL, dA, dB, dC, dH, c1, c2;

getline (file,line);
char * cline = new char [line.length()+1];while(newline == true){

currentClosestVal = 1000000;
std::strcpy (cline ,line.c_str());
hexcolor = strtok(cline, delim);
r_hex = strtok(NULL, delim);
g_hex = strtok(NULL, delim);
b_hex = strtok(NULL, delim);r = (float)atof(r_hex.c_str());
g = (float)atof(g_hex.c_str());
b = (float)atof(b_hex.c_str());

cie1 = rgb2lab (r, g, b);for (i = 0; i < 2100; i++)
{
cie2 = rgb2lab (red[i], green[i], blue[i]);
//challengeClosestVal = pow(cie1[0] - cie2[0], 2.0) + pow(cie1[1] - cie2[1], 2.0) + pow(cie1[2] - cie2[2], 2.0);
dL = cie1[0] - cie2[0];
dA = cie1[1] - cie2[1];
dB = cie1[2] - cie2[2];
c1 = sqrt(cie1[1] + cie1[2]);
c2 = sqrt(cie2[1] + cie2[2]);
dC = c1 - c2;
dH = sqrt(pow(dA, 2) + pow(dB,2) - pow(dC,2));
Kl = 2;
K1 = .048;
K2 = .014;
Sl = 1;
SC = 1 + K1*c1;
SH = 1 + K2*c1;

challengeClosestVal = sqrt(pow(dL/(Kl*Sl), 2) + pow(dC/(Kl*SC),2) + pow(dH/(Kl*SH), 2));if(challengeClosestVal < currentClosestVal){
currentClosestIndex = i;
currentClosestVal = challengeClosestVal;
}
}

ofile << hexcolor <<"; " << pantoneHexCodes[currentClosestIndex] <<";"<<endl; // prints The pantone color comparator
line = "";
newline = getline (file,line);

}//end of while loop

//close files
file.close();
ofile.close();
return 0;
}

float *rgb2lab (float r, float g, float b){

float var_r, var_g, var_b;
double X, Y, Z, var_X, var_Y, var_Z;
float ref_X =  95.047;  //Observer= 2°, Illuminant= D65
float ref_Y = 100.000;
float ref_Z = 108.883;
double cieL, cieA, cieB;
float *cie = new float[3];//Convert RGB to XYZ
//First set RGB values between 0-1
var_r = r/255;
var_g = g/255;
var_b = b/255;

if ( var_r > 0.04045 )
var_r = pow( ( var_r + 0.055 ) / 1.055 , 2.4);
else
var_r = var_r / 12.92;

if ( var_g > 0.04045 )
var_g = pow( ( var_g + 0.055 ) / 1.055 , 2.4);
else
var_g = var_g / 12.92;
if ( var_b > 0.04045 )
var_b = pow( ( var_b + 0.055 ) / 1.055 , 2.4);
else
var_b = var_b / 12.92;

var_r = var_r * 100;
var_g = var_g * 100;
var_b = var_b * 100;

//Convert RGB to XYZ
//Observer. = 2°, illuminant = D65
X = var_r * 0.4124 + var_g * 0.3576 + var_b * 0.1805;
Y = var_r * 0.2126 + var_g * 0.7152 + var_b * 0.0722;
Z = var_r * 0.0193 + var_g * 0.1192 + var_b * 0.9505;

//cout << "X: "<<X  <<"  Y: "  <<Y <<"  Z: "<<Z << endl;// Convert XYZ to CIELab
var_X = X / ref_X;          //ref_X =  95.047   Observer= 2°, Illuminant= D65
var_Y = Y / ref_Y;          //ref_Y = 100.000
var_Z = Z / ref_Z;          //ref_Z = 108.883
//cout << "var_X: "<<var_X  <<"  var_Y: "  <<var_Y <<"  var_Z: "<<var_Z << endl;

if ( var_X > 0.008856 ) {
var_X = pow(var_X, .3333333); }
else
var_X = ( 7.787 * var_X) + ( 16 / 116 );
if ( var_Y > 0.008856 ){
var_Y = pow(var_Y, .3333333); }
else
var_Y = ( 7.787 * var_Y) + ( 16 / 116 );
if  ( var_Z > 0.008856 ){
var_Z = pow(var_Z,  .3333333); }
else
var_Z = ( 7.787 * var_Z) + ( 16 / 116 );cieL = ( 116 * var_Y ) - 16;
cieA = 500 * ( var_X - var_Y );
cieB = 200 * ( var_Y - var_Z );

//cout << "L: "<<cie[0]  <<"  a: "  <<cie[1] <<"  b: "<<cie[2] << endl;
cie[0] = cieL;
cie[1] = cieA;
cie[2] = cieB;
//cout << "L: "<<cie[0]  <<"  a: "  <<cie[1] <<"  b: "<<cie[2] << endl;
return cie;

}

1

Решение

В вашем rgb2lab функция, которую вы создаете new float[3], Это происходит с каждым вызовом этой функции. Глядя на твой код, я не вижу, где память для этого освобождается при вызове delete в любом месте.

Это хорошая практика программирования, что каждый new в паре с delete, Также более важно, чтобы delete вызывается в каждом пути выполнения программы, если что-то создано с new,

Что происходит в вашем коде, так это то, что ваш rgb2lab функция вызывается 2100 раз для каждой строки, записанной в файл. Вы говорите, что ваша программа выходит из строя после того, как в файл записано около 62000 строк. В этом случае rgb2lab функция вызывается 130 200 000 раз и каждый раз теряет память.

РЕДАКТИРОВАТЬ:

У вас есть пара мест, где вы звоните new что ты должен delete, но самым большим нарушителем является итерация 2100 for цикл, который вызывает rgb2lab функционировать снова и снова. Поскольку вы используете динамически распределяемый массив, который возвращает функция, просто освободите память, когда вы закончите ее использовать.

for (i = 0; i < 2100; i++)
{
cie2 = rgb2lab (red[i], green[i], blue[i]);
//challengeClosestVal = pow(cie1[0] - cie2[0], 2.0) + pow(cie1[1] - cie2[1], 2.0) + pow(cie1[2] - cie2[2], 2.0);
dL = cie1[0] - cie2[0];
dA = cie1[1] - cie2[1];
dB = cie1[2] - cie2[2];
c1 = sqrt(cie1[1] + cie1[2]);
c2 = sqrt(cie2[1] + cie2[2]);
dC = c1 - c2;
dH = sqrt(pow(dA, 2) + pow(dB,2) - pow(dC,2));
Kl = 2;
K1 = .048;
K2 = .014;
Sl = 1;
SC = 1 + K1*c1;
SH = 1 + K2*c1;

challengeClosestVal = sqrt(pow(dL/(Kl*Sl), 2) + pow(dC/(Kl*SC),2) + pow(dH/(Kl*SH), 2));if(challengeClosestVal < currentClosestVal){
currentClosestIndex = i;
currentClosestVal = challengeClosestVal;
}
}
delete [] cie2;  // <-- Free up the memory here!
1

Другие решения

Я не понимаю, почему вы используете new оператор (за исключением того, что вы пришли из фона Java или C #). Вы можете передавать результаты без использования нового оператора.

Например:

void rbg_to_lab (float r, float g, float b,
float& cie[3])
{
// ...
}

Проходя cie массив в качестве ссылки, вы можете изменить переменную вызывающего непосредственно с выделением любого new объекты памяти (и не нужно delete память тоже.)

Другое решение заключается в создании структуры для cie значения и вернуть структуру:

struct Cie_Values
{
float cie_1;
float cie_2;
float cie_3;
};

Cie_Values rgb_to_lab(float r, float g, float b)
{
Cie_values cie;
// Perform conversion
return cie;
}
1

По вопросам рекламы [email protected]