避免C ++中的内存泄漏?

时间:2017-03-27 13:27:14

标签: c++ arrays global-variables

我开始使用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;
}

所以我很高兴知道我的代码出了什么问题,为什么会这样呢。我听说我们不应该使用全局变量,这可能有助于我理解为什么。

顺便说一句,我有兴趣就如何使用良好的语法编写正确的代码提出一些建议,而不会出现范围问题。因为我想学习如何编写一个最通用的功能#34;可能,所以我可以拉它并在其他程序中使用它与其他变量。

提前感谢您的支持

P.S。:我使用g ++作为编译器和2011 C ++标准

3 个答案:

答案 0 :(得分:-2)

现代C ++的一个好习惯是永远不要使用手动内存管理 - 如果你在c ++ 11或更高版本的代码中看到newdelete,那就是代码嗅觉的迹象。

改为使用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个元素的数组,然后你做了很多未分配的内存覆盖,然后尝试释放它。这不会奏效。

在您从NumberT读取std::cin之后移动数组分配,它应该会大大改善。

接下来的改进将是在没有全局变量的情况下切换到更具功能性的风格(你不需要它们)。

然后切换到使用std::shared_ptr s。

答案 1 :(得分:-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 :(得分:-2)

正如对方说的那样。您的阵列初始化是个问题。 一般来说,由于你不知道元素的初始大小,我会立即考虑向量。在这种情况下,您可以删除&#34;有多少元素。&#34;并引入退出字符或解析X分隔值。

当然,使用数组并没有错,但你必须(重新)用正确的大小初始化它们。因此,在你得到NumberT之后。然而,对于数组与向量,请检查此Arrays Vs Vectors

我已经使用向量发布了一个实现,但仍然基于您的方法。

(注意!:这段代码效率不高,因为它会执行很多矢量副本,而且不会引入新的概念。请通过引用和std :: move自己搜索参数)

#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;
}