C ++会把这个函数泄漏吗?

时间:2010-01-21 15:17:50

标签: c++ memory-leaks

我已经开始为练习编写一个简单的控制台Yahtzee游戏。我只是对这个功能是否会泄漏内存有疑问。每次需要重新滚动骰子时都会调用滚动功能。

它的作用是创建一个动态数组。第一次使用它会存储5个随机值。对于下一次运行,除了你想要保留的骰子外,它只会重新滚动。我有另一个功能,但由于它与这个问题无关,我把它留了出来

主要功能

int *kast = NULL;           //rolled dice
int *keep_dice = NULL;    //which dice to re-roll or keep

kast = roll(kast, keep_dice);
delete[] kast;

这是函数

int *roll(int *dice, int *keep) {

    srand((unsigned)time(0));
    int *arr = new int[DICE];
    if(!dice)
    {
        for(int i=0;i<DICE;i++)
        {

            arr[i] = (rand()%6)+1;
            cout << arr[i] << " ";
        }
    }
    else
    {
        for(int i=0;i<DICE;i++)
        {
            if(!keep[i])
            {
                dice[i] = (rand()%6)+1;
                cout << "Change ";
            }
            else
            {
                keep[i] = 0;
                cout << "Keep ";
            }
        }
        cout << endl;
        delete[] arr;
        arr = NULL;
        arr = dice;

    }
    return arr;
}

4 个答案:

答案 0 :(得分:12)

是的,它可以泄漏。例如,使用cout可以抛出异常,如果是,则永远不会调用delete

您可能需要考虑返回std::vector,而不是自己分配动态数组。更好的是,将您的函数转换为适当的算法,该算法采用迭代器(在本例中为back_insert_iterator)并将其输出写入其中。

编辑:仔细看一下,我觉得有必要指出我完全不喜欢这段代码的基本结构。你有一个功能,它真的做了两种不同的事情。您还有一对阵列,它们依赖于并行寻址。我将其重组为两个单独的函数,rollre_roll。我将数据重组为结构数组:

struct die_roll { 
    int value;
    bool keep;

    die_roll() : value(0), keep(true) {}
};

要进行初始滚动,您可以将这些向量(或数组,如果您真正坚持的话)传递给填充初始值的roll函数。要进行重新滚动,请将向量传递给re-roll,然后重新滚动以获取keep成员已设置为false的任何die_roll的新值。

答案 1 :(得分:4)

使用(stack-allocated)std::vector而不是数组,并将对它的引用传递给函数。这样,你就可以确定它不会泄漏。

答案 2 :(得分:4)

分配内存的方式令人困惑:函数内部分配的内存必须通过函数外部的代码释放。

为什么不重写这样的东西:

int *kast = new int[DICE];           //rolled dice
bool *keep_dice = new bool[DICE];    //which dice to re-roll or keep
for (int i = 0; i < DICE; ++i)
    keep_dice[i] = false;

roll(kast, keep_dice);

delete[] kast;
delete[] keep_dice;

这样可以很好地匹配您的newdelete。关于函数:因为我们将keep_dice全部设置为false,这两个参数都不是NULL,它总是修改dice而不是返回一个新数组,它简化为:

void roll(int *dice, int *keep) {
    for(int i=0;i<DICE;i++)
    {
        if(keep[i])
        {
            keep[i] = false;
            cout << "Keep ";
        }
        else
        {
            dice[i] = (rand()%6)+1;
            cout << "Change ";
        }
    }
    cout << endl;
}

此外,您应该将srand电话移至程序的开头。重播非常不利于随机性。

答案 3 :(得分:0)

我的建议是抽出时间购买/借阅并阅读Scott Meyers Effective C ++ 3rd Edition。为了成为一名高效的C ++程序员,您将节省数月的痛苦。我从个人的,痛苦的经历中说话。