Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [C++] Проблемы с памятью: глубо-о-окая рекурсия


Автор: l0ser 14.4.2010, 03:53
Преамбула: написал консольную програмульку в Visual C++ 6.0 для игры в реверси. Оценка каждого из возможных ходов сделана рекурсивной функцией на нужную глубину. На дне рекурсии позиция оценивается по количеству очков и по «стоимости» ячейки, куда делается ход.

Проблема: заметил, что при глубине рекурсии от 6 иногда начинаются глюки – портится доска, находятся ложные ходы. Вылизывал программу, но так ничего и не добился. Поскольку я программирую «индийским» методом, рекурсия делает кучу вызовов new и delete.

Главный вопрос: возможны ли именно в VC++ 6 проблемы с памятью при интенсивном выделении/освобождении? Или всё-таки искать ошибку у себя?

Второстепенный вопрос: чтобы выяснить самым варварским и антигуманным способом, моя ли это ошибка, ставил Мандриву. В ней программа отказалась компилироваться (даже под рутом) из-за непонятных ругательств в адрес любых операторов вывода – от printf до cout. Посоветуйте нубский дистрибутив линукса с компилятором.  smile 

Могу приложить исходники.

Автор: Coder 14.4.2010, 04:02
И при чем тут Мандрива....

Цитата

Могу приложить исходники.

Хорошая идея!

Автор: l0ser 14.4.2010, 04:13
Цитата(Coder @ 14.4.2010,  04:02)
И при чем тут Мандрива....

Цитата

Могу приложить исходники.

Хорошая идея!

Мандрива ни при чём. smile Не стала она кушать мою бяку. Но я хочу найти дистр линукса, где не надо будет думать, что написать в конфиги и какие пакеты скачать перед тем, как скомпилировать Хелловорлд. Просто потому что про конфиги и пакеты я читал только в мировом IT фольклоре. smile

Прикладываю зипчик исходников.

Автор: Andrey44 14.4.2010, 08:20
Цитата(l0ser @  14.4.2010,  03:53 Найти цитируемый пост)
Главный вопрос: возможны ли именно в VC++ 6 проблемы с памятью при интенсивном выделении/освобождении? Или всё-таки искать ошибку у себя?
В VC++ 6 проблем быть не должно, работают ведь в STL контейнеры, и нормально. Скорее всего искать ошибку надо у тебя в коде искать.

Цитата(l0ser @  14.4.2010,  03:53 Найти цитируемый пост)
программирую «индийским» методом
 smile Не только ты, я много таких встречал smile 

Автор: l0ser 14.4.2010, 08:33
Цитата(Andrey44 @ 14.4.2010,  08:20)
Цитата(l0ser @  14.4.2010,  03:53 Найти цитируемый пост)
Главный вопрос: возможны ли именно в VC++ 6 проблемы с памятью при интенсивном выделении/освобождении? Или всё-таки искать ошибку у себя?
В VC++ 6 проблем быть не должно, работают ведь в STL контейнеры, и нормально. Скорее всего искать ошибку надо у тебя в коде искать.

Просто уж больно дофига там new-delete происходит. Вот я и засомневался.

Автор: Coder 14.4.2010, 08:51
Цитата(l0ser @  14.4.2010,  16:33 Найти цитируемый пост)
Просто уж больно дофига там new-delete происходит. Вот я и засомневался.


Ну и пусть происходят. Судя по описанию проблемы ты просто коцаешь чужую память.

Исходник лень весь смотреть.... давай сюда только рекурсивную функцию

Автор: l0ser 14.4.2010, 09:01
Код

int val(const desk &d, const move &m, char depth)
{
    int value;
    if (depth)
    {
        desk dm = d;
        dm.make_move(m);
        char i, n;
        int v[MAX_POSS];
        move *mvf = dm.find(OPPONENT(m.color), n); //OPPONENT - макрос
        if (!n)
            value = m.sum + pos_val[m.x][m.y]; //pos_val - массив ценности клеток доски
        else
        {
            for (i = 0; i < n; ++i) v[i] = val(dm, mvf[i], depth - 1);
            int max = v[0];
            for (i = 1; i < n; ++i) if (v[i] > max) max = v[i];
            value = m.sum - max;
        }
        delete [] mvf;
    }
    else
        value = m.sum + pos_val[m.x][m.y];

    return value;
}


предполагается, что противник всегда выбирает «наилучший» ход

Автор: Фантом 14.4.2010, 09:32
По описанию это больше напоминает не проблемы с выделением/освобождением памяти, а попытки в каком-то месте вылезти за границы массива. Попробуйте проверить это.

Что касается второго вопроса - практически любой дистрибутив. Проблема не в Мандриве, проблема в кривом VC++, в котором слишком много отклонений от стандарта языка.

Автор: l0ser 14.4.2010, 09:37
Цитата(Фантом @ 14.4.2010,  09:32)
Что касается второго вопроса - практически любой дистрибутив. Проблема не в Мандриве, проблема в кривом VC++, в котором слишком много отклонений от стандарта языка.

Скорее дело в моих кривых руках. Ибо я менял всячески операторы вывода, и всегда компилятор gcc матерился непонятными словами именно на них, спокойно переваривая все остальное. Да и потом, никаких специфичных для Виндофс функций я не вызывал.

Попробую помедитировать над границами... но если ошибка такова, то уж больно редко она происходит. smile

Автор: Coder 14.4.2010, 09:46
Цитата(l0ser @  14.4.2010,  17:37 Найти цитируемый пост)
Да и потом, никаких специфичных для Виндофс функций я не вызывал.


А виндовс сама специфична smile 

А вот смотри. Может дело тут:

Код

    move *possible = new move[MAX_POSS], search;
    char i, x, y, min;
    bool dir_found;
    char opponent = OPPONENT(pl);

    count = 0;
    for (y = 0; y < 8; ++y)
        for (x = 0; x < 8; ++x)

        {

                              ........
            if (search.sum) //move possible
            {
                search.x = x;
                search.y = y;
                search.color = pl;
                possible[count++] = search;
            }
.......
........


MAX_POSS = 20
а цикл выполняется 64 раза

Автор: l0ser 14.4.2010, 10:01
Цитата(Coder @ 14.4.2010,  09:46)
А вот смотри. Может дело тут:

...

MAX_POSS = 20
а цикл выполняется 64 раза

Не. :( Я там прикидывал – в реверси максимум 16 возможных ходов было, специально такую позицию искал. Вообще, можно примерно 28 выжать, но такую позицию из начальной не получишь (вначале по две фишки крест-накрест стоят).

Автор: assasincore 14.4.2010, 10:54
Ты что используеш много памяти? гигабйт? два? хотя бы 100 метром? 
breakpoint -> task manager/ process explorer. 

Короче у тя бага... ТВОЯ! А не компилятора... отладчик в зубы и...

Автор: l0ser 14.4.2010, 21:19
Цитата(assasincore @ 14.4.2010,  10:54)
Ты что используеш много памяти? гигабйт? два? хотя бы 100 метром? 
breakpoint -> task manager/ process explorer. 

Короче у тя бага... ТВОЯ! А не компилятора... отладчик в зубы и...

Спасибо за вежливый и содержательный ответ! smile
Попрошу удалить тему.

Автор: Фантом 14.4.2010, 22:50
Цитата(l0ser @  14.4.2010,  09:37 Найти цитируемый пост)

Скорее дело в моих кривых руках. Ибо я менял всячески операторы вывода, и всегда компилятор gcc матерился непонятными словами именно на них, спокойно переваривая все остальное. Да и потом, никаких специфичных для Виндофс функций я не вызывал.

В C++ есть такие полезные штуки - "пространства имен", которые существенны в том числе и для операторов потокового ввода-вывода. Соответственно, корректная программа на С++ должна либо где-нибудь в начале содержать using namespace std;, либо, что более правильно,  содержать явную конкретизацию области видимости (например, вида std::cout << "Ляляля" << std::endl;).

Цитата(l0ser @  14.4.2010,  09:37 Найти цитируемый пост)

Попробую помедитировать над границами... но если ошибка такова, то уж больно редко она происходит. 

Она будет вылезать только в том случае, если при наложении кусков разных массивов происходит "неправильная" перезапись данных в каком-то массиве. Это совсем не всегда может случаться. Возможно, конечно, что дело не в этом, но подобные грабли для C++ действительно стандартны, и видимые проявления похожи.

Автор: En_t_end 15.4.2010, 07:19
Тема перенесена! 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)