2017-03-27 97 views
-1

我開始用C++進行編碼,最近我遇到了一個問題,我找不到解決方案,因爲我不明白我的錯誤。避免C++中的內存泄漏?

我的程序是將開爾文轉換爲攝氏溫度,但它不能在連續3個以上的溫度下進行。只要我通過4,它給我正確的轉換與內存問題(超出範圍?)。

錯誤「XXX」:雙人免費或損壞(出):0x0000000001c94c40

而當我進入四個以上溫度下,它給出了一些隨機數,這可能是其他不會忽略的值。

這是我的程序。

#include <iostream> 

using namespace std; 

unsigned int NumberT {0};   //Definition of the global variables 
double* Kelvin=new double[NumberT]; 
double* Celsius=new double[NumberT]; 
unsigned int i=0; 


double* Conversion (double, double, unsigned int) //Conversion function 
{ 
    for(unsigned int i=0;i<NumberT;++i) 
    { 
     Celsius[i]=Kelvin[i]-273.15; 
    } 
    return Celsius; 
} 


void printTemperatures (double, double, unsigned int) //Print function 
{ 
    for(unsigned int i=0;i<NumberT;++i) 
    { 
     cout<<"The temperature is "<< Kelvin[i] <<" [K], which is "<< Celsius[i] <<" [C]"<<endl; 
    } 
    return; 
} 


int main()      //Main 
{ 
    cout<<"How many temperatures do you want to enter?"<<"\n"; 
    cin>>NumberT; 

    cout<<"What are the temperatures?"<<"\n"; 
    for (unsigned int i=0;i<NumberT;++i) 
    { 
     cin>>Kelvin[i]; 
    } 

    Conversion (Kelvin[i], Celsius[i], NumberT); 
    printTemperatures (Kelvin[i], Celsius[i], NumberT); 


    delete [] Celsius; 
    delete [] Kelvin; 
    return 0; 
} 

所以我會很高興知道我的代碼有什麼問題,爲什麼它是這樣的。我聽說我們不應該使用全局變量,這可能會幫助我理解原因。

順便說一下,我有興趣就如何寫一個合適的代碼與一個良好的語法,沒有範圍問題一些建議。因爲我想學習如何編寫一個可能性最「普遍」的函數,以便我可以將它拉到另一個帶有其他變量的程序中。

預先感謝您的支持

PS:我用G ++作爲編譯器和2011年的C++標準

+3

當您進行內存分配時,NumberT'爲0 - 在'main'內移動全局變量和內存分配,首先讀取'NumberT'的值,然後執行實際的內存分配。你也應該正確地設置你的代碼格式 - 你有一些其他的錯誤,一旦格式化代碼會變得更加明顯。 –

+4

你真的應該使用'std :: vector '而不是'double *'。 – NathanOliver

+0

你分配的數組的大小爲0.我不記得這樣的動作本身是不是一個未定義的行爲,而是試圖將數據寫入這樣的數組 - 確切地說是。 –

回答

-2

在現代C++寫的好習慣是從來不使用人工內存管理 - 如果你看到newdelete在C++ 11或更高版本的代碼中是代碼異味的標誌。

使用std::make_shared/std::make_unique改爲使用value typesstd::move

查看Herb Sutter最新的talk "Leak-Freedom in C++ by default"

爲了您的具體的例子

unsigned int NumberT {0}; //Definition of the global variables double* Kelvin=new double[NumberT];

您創建這裏0元素的數組,然後你做了很多的未分配內存的覆蓋,然後嘗試釋放它。這不起作用。

將陣列分配移動到您已經從std::cin讀取NumberT之後,它應該會有相當大的提高。

接下來的改進是切換到沒有全局變量的更多功能樣式(你不需要它們)。

然後切換到使用std::shared_ptr s。

+0

C++ 11中不存在羞恥'std :: make_unique',所以你必須至少在代碼中看到「'new」;) –

+0

你仍然在使用'new'在那可能導致泄漏。真正的'std :: make_unique'不會在構造失敗時泄漏。 – NathanOliver

+0

是的,但這可以修復。我切換到C++ 14,所以它不再是我的問題。 – Berkus

-2

當你做內存分配時,你的問題是NumberT0
當你這樣做:執行

double* Kelvin=new double[0]; 

沒有初始化,使指針具有不確定的值。 寫入和讀取此內存具有未確定的行爲。

當您對具有不確定值的指針使用delete[]時,您的代碼可能會崩潰。

此問題非常適合使用vector<double>而不是double[]數組,因此沒有理由不使用此容器提供的動態內存處理功能。

使用如下例:

//Replace arrays with vectors 
vector<double> Kelvin; 
vector<double> Celsius; 

//in your main to read user input 
for (unsigned int i=0;i<NumberT;++i) 
{ 
    double read; 
    cin >> read; 
    Kelvin.push_back(read); 
} 

//In your conversion function 
for (std::vector<double>::iterator it = Kelvin.begin(); it != Kelvin.end(); ++it) 
{ 
    Celsius.push_back((*it)-273.15); 
} 

其他提示:

- 你不需要聲明全局變量(你可以在你的main()例如開始時聲明它),並通過referece傳遞變量,像這樣:

void Conversion (vector<double> & Kelvin, vector<double> & Celsius); 

- 當vector情願的超出範圍(在你main()月底),他們會做的delete爲你工作。

-2

正如對方所說。你的數組初始化是個問題。通常,由於您不知道元素的初始大小,因此我會立即考慮向量。在這種情況下,您可以刪除「多少個元素..」並引入一個退出字符或解析X個分隔值。

當然,使用數組並不是錯的,但您必須(重新)使用正確的大小對它們進行初始化。因此在您獲得NumberT後。然而,對於陣列vs向量檢查Arrays Vs Vectors

我已經發布了一個使用向量的實現,但仍然是基於你的方法。

(注意!:這個代碼是沒有效率的,因爲它做了很多載體拷貝的,這是不引入新的概念,請參考和std ::移動對自己的搜索參數)

#include <iostream> 
#include <vector> 
#include <algorithm> 

std::vector<double> ToCelcius(std::vector<double> kelvinValues) //Conversion function 
{ 
    std::vector<double> celciusValues; 
    for (auto value : kelvinValues) 
    { 
     celciusValues.push_back(value - 273.15); 
    } 
    return celciusValues; 
} 


void PrintTemperatures(std::vector<double> kelvinSource, std::vector<double> celsiusSource) //Print function 
{ 
     for (uint16_t valueIndex = 0; valueIndex < kelvinSource.size(); valueIndex++) 
     { 
      std::cout << "The temperature is " << kelvinSource.at(valueIndex) << " [K], which is " << celsiusSource.at(valueIndex)<< " [C]" << std::endl; 
     } 
} 


int main()      //Main 
{ 
    uint16_t numberOfValues; 
    std::cout << "How many temperatures do you want to enter?" << "\n"; 
    std::cin >> numberOfValues; 

    std::cout << "What are the temperatures?" << "\n"; 
    std::vector<double> kelvinValues; 

    double value; 
    for (uint16_t i = 0; i< numberOfValues; ++i) 
    { 
     if (std::cin >> value) { 
      kelvinValues.push_back(value); 
     } 
     continue; 
    } 
    auto celciusValues = ToCelcius(kelvinValues); 
    PrintTemperatures(kelvinValues, celciusValues); 

    return 0; 
}