Форум программистов, компьютерный форум CyberForum.ru

Ошибка в работе с памятью - C++

Восстановить пароль Регистрация
 
Tim Berg
0 / 0 / 0
Регистрация: 04.12.2012
Сообщений: 13
07.05.2013, 19:15     Ошибка в работе с памятью #1
После использования программы и последующего выхода из нее возникает ошибка HEAP CORRUPTION DETECTED.
Хотелось бы узнать, в чем причина и как в данном случае правильно выделить и освободить память.
Был бы очень признателен, если б кто-нибудь смог отработать программу и указать на допущенные ошибки, т.к. очень нужно чтобы программа работала гладко, без ошибок.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include "stdafx.h"
#include "iostream"
#include "Stack.h" // библиотека "Стек"
 
using namespace std;
 
int main()
{
    int choice; // Выбор операции над стеком
    Stack st; // Создаем стек
    bool quit = true; // если false, выходим из цикла
 
    while (quit == true)
    {
        cout << "(0)Quit (1)Push (2)Pop (3)Show (4)Tail: ";
        cin >> choice; // номер операции
 
        switch (choice)
        {
        case 1: // Добавить элемент в стек
            st.Push();
            st.Show();
            break;
 
        case 2: // Извлечь элемент из стека
            st.Pop();
            st.Show();
            break;
 
        case 3: // Показать текущие значения элементов стека
            st.Show();
            break;
 
        case 4: // Показать вершину стека (последний элемент)
            st.Tail();
            break;
 
        default: // В остальных случаях выходи из цикла
            quit = false;
            break;
        }
    }
 
    system("pause"); // стоп-консоль
 
    return 0;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// ==================================== Stack ======================================
// 
// Класс Stack - реализует структуру данных "стек", 
// позволяет оперировать символьными данными.
// При каждом проталкивании в "стек" элемент записывается в массив char'ов,
// а length увеличивается на единицу.
// При извлечении элемента из "стека" length уменьшается на единицу.
//
// =================================================================================
 
 
class Stack
{
public:
    Stack();                // конструктор, инициализирует length нулевым значением,
                            // выделяет память для data
    ~Stack();               // деструктор, освобождает память, выделенную под data
    void Push();            // проталкивание элемента в стек
                            // увеличивает length на 1
    void Pop();             // извлечение элемента из стека
                            // уменьшает length на 1
    void Tail();            // отображает вершину стека
    void Show() const;      // отображает эелементы стека
 
private:
    char *data; // элементы стека
    int length; // длина стека
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "stdafx.h"
#include "iostream"
#include "Stack.h"
 
using namespace std;
 
Stack::Stack():
    length(0), // инициализация нулевой длины стека
    data(new char[])
{}
 
Stack::~Stack()
{
    delete[] data;
    data = 0;
}
 
void Stack::Push() // добавление элемента в стек
{
    char element; // элемент стека
 
    cout << "New element: "; // приглашение добавить элемент в стек
    cin >> element;
 
    data[length] = element; // эелементы храним в массиве
    length++; // при добавлении элемента увеличиваем длину стека
}
 
void Stack::Pop() // извлечение элемента из стека
{
    if (length > 0) // если стек не пустой, извлекаем элемент
    {
        cout << "Pop element: " << data[length - 1] << endl;
        length--;
    }
    // иначе - сообщение о пустом стеке в функции Show()
}
 
void Stack::Tail() // отображаем вершину стека
{
    if (length > 0) // если стек не пустой,
    {
        cout << "Tail element: " << data[length - 1] << endl;
        // отображаем вершину стека
    }
    else // если пустой,
    {
        cout << "Stack is empty!" << endl;
    }
}
 
void Stack::Show() const
{
    if (length > 0) // если стек не пустой,
    {
        for (int i = 0; i < length; i++)
        {
            cout << data[i]; // отображаем все эелементы
            if (i != length - 1) // после каждого элемента, кроме последнего
            {
                cout << ", "; // ставим запятую
            }
            else // если элемент последний,
            {
                cout << endl; // то перевод строки
            }
        }
    }
    else // если стек пустой
    {
        cout << "Stack is empty!" << endl;
    }
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
anmartex
...
 Аватар для anmartex
1699 / 1192 / 494
Регистрация: 12.02.2013
Сообщений: 1,978
07.05.2013, 19:55     Ошибка в работе с памятью #2
Tim Berg, сразу вопрос к вам: по вашему мнению сколько выделится памяти в конструкторе под поле data? Я не знаю как MS компилятор ведёт себя, но gcc сразу ругнулся. Как я понимаю, это аналог new char[0] (т.е. тогда проще data(NULL)), но я могу и ошибаться. Но в любом случае, вы в методе Push спокойно и без всяких сомнений добавляете элементы: data[length++] = element. И теперь опять возвращаюсь к вопросу: так сколько вы выделили памяти под data?
Tim Berg
0 / 0 / 0
Регистрация: 04.12.2012
Сообщений: 13
07.05.2013, 22:46  [ТС]     Ошибка в работе с памятью #3
Могу написать глупость, но, как мне кажется, такой прием приемлим, т.к. это динамический массив (или нет?) и я могу добавить столько элементов, сколько мне позже понадобится.
С++ уже плохо помню, надо вспоминать.
На VS у меня компилируется, работает и ошибка вылетает только по окончании работы программы.
anmartex
...
 Аватар для anmartex
1699 / 1192 / 494
Регистрация: 12.02.2013
Сообщений: 1,978
08.05.2013, 04:19     Ошибка в работе с памятью #4
Цитата Сообщение от Tim Berg Посмотреть сообщение
Могу написать глупость, но, как мне кажется, такой прием приемлем
Не обижайтесь, но вы написали глупость.

Цитата Сообщение от Tim Berg Посмотреть сообщение
динамический массив
А что есть динамический массив? Вы объявляете char* data - это ничто иное как просто указатель на область памяти. Когда вы пишите, к примеру, data = new char[10] тем самым вы выделяете (резервируете) память размером sizeof(char) * 10 (т.е 10 байт) и адрес на начало этого вектора (выделенного участка памяти) присваиваете data. Контроль выхода за границы выделенной памяти никто кроме вас осуществлять не будет. Я не знаю сколько MS компилятор выделит памяти при такой записи new char[], но в любом случае это либо 0, либо 1.

Цитата Сообщение от Tim Berg Посмотреть сообщение
и я могу добавить столько элементов, сколько мне позже понадобится.
Эх, если бы всё было так просто!

Цитата Сообщение от Tim Berg Посмотреть сообщение
работает и ошибка вылетает только по окончании работы программы
Ваши действия из разряда Undefined behavior. Если бы вы попробовали поработать с большим количеством символов, то ваша программа вылетела бы раньше.
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
08.05.2013, 09:53     Ошибка в работе с памятью #5
Цитата Сообщение от anmartex Посмотреть сообщение
выделит памяти при такой записи new char[], но в любом случае это либо 0, либо 1.
MS генерит в таком случае код, эквивалентный new char[0]. Не очень понятно, почему они разрешают не писать число в скобках, ну, пусть это будет на их совести.
Yandex
Объявления
08.05.2013, 09:53     Ошибка в работе с памятью
Ответ Создать тему
Опции темы

Текущее время: 04:23. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru