2013-07-25 62 views
1

我只是回到在C編程。我編寫了一個程序,該程序應該從文件中讀取十六進制顏色,並將它們與程序中標識的顏色數組進行比較,以確定哪一個最接近顏色,然後將原始顏色和最接近的顏色寫入文件。出於某種原因,寫了大約62,000行左右的程序後,堆棧轉儲出來了。我正在閱讀的文件中有大約1600萬種顏色。我希望有人能夠用我的代碼指出我正確的方向來解決這個問題。雖然循環導致堆棧轉儲和程序崩潰在C++

代碼如下,我沒有將數組粘貼到紅色,綠色,藍色或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

代碼縮進。請使用它。 – Borgleader

+0

您應該瞭解如何閱讀崩潰轉儲和如何調試。 – marcinj

+0

你用調試符號編譯過嗎?如果是這樣,是否有核心文件?你有沒有用調試器檢查過核心文件?崩潰是否可重複?每次都在同一次迭代中發生嗎?如果你在linux上,編譯器的'-g'標誌將添加調試符號,並檢查覈心 - 'gdb <可執行文件>' – Macattack

回答

1

在你rgb2lab功能創建new float[3]。每次調用此函數都會發生這種情況。看着你的代碼,我看不到在哪裏爲這個存儲器釋放了任何地方的電話delete

這是一個很好的編程習慣,每new配對delete。如果使用new創建了某些內容,則在程序的每個執行路徑中調用delete也更重要。

代碼中發生的事情是,對於寫入文件的每一行,您的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! 
+0

謝謝我欣賞這一點。如果我試圖返回刪除之前創建的數組,我會在哪裏放置刪除? – user1370238

+0

避免使用'new'和'delete',按值或引用傳遞。 –

+1

完成使用返回的數組後,您應該放置'delete []'。分配和刪除數組會使您的程序變慢。 –

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; 
} 
+0

謝謝托馬斯,我感謝幫助! – user1370238