Форум программистов, компьютерный форум, киберфорум
Наши страницы

Ошибка при освобождении памяти - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ посоветуйте книжку (на экзамен шпору) http://www.cyberforum.ru/cpp-beginners/thread427879.html
Доброго времяни суток. Посоветуйте пожалуйста книжку на экзамен ( в качестве шпоры) чтоб была понятная и небольшая по основам с++ по началу. Зарание благодарю тех, кто просмотрел тему и решил мне...
C++ Как осуществляется преобразование типов (для чего)? Как осуществляется преобразование типов (для чего)? int *p=(int*)str; // ругается на p Спасибо :) P.s Си http://www.cyberforum.ru/cpp-beginners/thread427868.html
Неименованые каналы C++
Почему при работе с pipe() в отце и сыновьям процессе необходимо закрывать ненужные дискрипторы?
Конструктор копирования C++
Помогите пожалуйста разобраться, необходимо добавить конструктор копирования, теорию знаю, а как на практике применить не знаю. Программа вот - http://zalil.ru/32492444. Добавлено через 33 минуты...
C++ Шаблоны C++ http://www.cyberforum.ru/cpp-beginners/thread427864.html
Написал template на С++, но он нифига не компилица, пишет мол типа не могу string в int преобразовать в строчке int out_param = (int)param; #include <stdio.h> #include <conio.h> #include...
C++ Необходимо найти максимальный элемент матрицы, используя несколько потоков Добрый день программисты, необходимо выполнить поиск наименьшего элемента матрицы используя количество потоков равное количеству строк данной матрицы. Каждый поток находит минимальный элемент своей... подробнее

Показать сообщение отдельно
AlexSome
0 / 0 / 0
Регистрация: 14.01.2012
Сообщений: 6

Ошибка при освобождении памяти - C++

14.01.2012, 05:48. Просмотров 811. Ответов 10
Метки (Все метки)

Здравствуйте. Знаю, что тема уже много раз поднималась в самых разнообразных местах и с очень отличающимися примерами, но, увы, я тоже с ней столкнулся, и не могу никак найти свою ошибку.

В общем, решил я написать библиотеку длинной арифметики. Так, для себя. Раньше уже таким занимался, но теперь решил сделать всё красиво и через классы. Даже не дойдя до самих арифметических операций, столкнулся с ошибкой при использовании оператора delete.

В общем, вот:

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
 
const unsigned int max_digits = 4; // сколько десятичных цифр может поместиться в одном разряде класса number
const unsigned int max_value = 65535; // максимальное значение выбранного типа
 
class number
{
    private:
    unsigned int* base;
    public:
    number();
    number(const number& obj); // конструктор копии
    void clear_nulls(); // очистка незначащих нулей
    void input();
    void output();
    friend bool operator== (number obj1, number obj2);
};
 
number::number() // создание нулевого числа
{
    base = new unsigned int[2];
    base[0] = 1; // длина нулевого числа
    base[1] = 0; // сам ноль
}
 
number::number(const number& obj)
{
    base = new unsigned int [obj.base[0] + 1]; // выделяем столько же памяти (1 для разряда размера)
    for (unsigned int i = 1; i<= base[0]; i++)
        base[i] = obj.base[i]; // копирование разрядов
}
 
void number::clear_nulls()
{
    unsigned int new_n = base[0]; // длина нового слова
    while (base[new_n] == 0)
        new_n--; // доходим до старшего ненулевого разряда
    if (new_n < base[0]) // если есть смысл очищать
    {
        unsigned int* temp_array = new unsigned int [new_n+1]; // создаём новый массив + место для разряда размера
        temp_array[0] = new_n; // он будет новой длины
        for (unsigned int i=1; i<=new_n; i++)
            temp_array[i] = base[i]; // переносим значения из изначального массива
        delete []base; // очищаем изначальный массив
        // так как temp_array очистится при выходе из видимости, то опять выделяем память под base
        // код идентичный коду выше
        base = new unsigned int [new_n+1];
        base[0] = new_n;
        for (unsigned int i=1; i<=new_n; i++)
            base[i] = temp_array[i];
        delete []temp_array;
    }
}
 
void number::input()
{
    delete []base; // очистка предидущего содержания числа
    // т.к. мы не знаем, каких размеров число мы введём, то зададим максимальный
    base = new unsigned int [max_value];
    base[0] = max_value;
    for (unsigned int i=1; i<=max_value; i++)
        base[i] = 0; // обнуление числа
 
    unsigned int signs_count = 0; // число введённых знаков
    char curr_char; // текущий введённый символ
    cin.get(curr_char); // считывание символа
    while (isdigit(curr_char)) // работа до тех пор, пока считанный символ - цифра
    {
        signs_count++; // прибавляем счётчик считанных символов
        unsigned int temp_add; // будет использовать при сдвиге цифр
        temp_add = curr_char - '0'; // изначально равен введённой цифре
        for (unsigned int i=1; i <= ( signs_count-1 ) / max_digits + 1; i++) // (s_c-1) / max_digits + 1 - число разрядов, которые придётся сдвигать (экономия времени)
        {
            base[i] *= 10; // сдвиг разряда влево на 1
            base[i] += temp_add; // вносим в его младший разряд наше число
            temp_add = base[i] / pow(10, max_digits); // делим текущий разряд на его максимальную вместимость (степень десятки)
            base[i] %= (unsigned int)pow(10, max_digits); // откидываем старший (не из имеющихся, а заданный) разряд
        }
        cin.get(curr_char); // считывание следующего символа
    }
 
    this->clear_nulls(); // очищаем незначащие нули
}
 
void number::output()
{
    unsigned int i = base[0]; // старший разряд
    cout << base[i]; // вывели его (без значащих нулей)
    i--; // сместились на разряд влево
    while (i >= 1) // пока не дошли до 0го разряда (количество разрядов)
    {
        cout<<setfill('0')<<setw(max_digits)<<base[i]; // вывели, даже если есть нули
        i--; // смещаемся дальше влево
    }
}
 
bool operator==(number obj1, number obj2)
{
    if (obj1.base[0] != obj2.base[0]) // если не совпадают длины, то это явно не одинаковые числа
        return false;
    else
    {
        unsigned int i = 1;
        bool eq = true; // допускаем, что числа равны
        while (i <= obj1.base[0] && eq) // пока ещё не дошли до конца и пока не опровергли гипотезу о равности
        {
            if (obj1.base[i] == obj2.base[i]) // если в данном месте числа равны - идём дальше
                i++;
            else
                eq = false; // если хоть в одном месте числа не равны - сразу выход
        }
        return eq;
    }
}
 
int main()
{
    number numb1;
    numb1.input();
    number numb2;
    numb2.input();
    cout << boolalpha << (numb1 == numb2);
    cin.get();
    return 0;
}
Код комментировал для себя, надеюсь, и вам будет всё понятно.
При выполнении выдаёт (замечу: ошибка происходит именно на строке "numb2.input();", что есть загадка: первый раз, для первого объекта, всё проходит гладко, а для второго - ошибка):
123
123
*** glibc detected *** /home/alex/CB/long_ar/bin/Debug/long_ar: double free or corruption (out): 0x0804b028 ***
======= Backtrace: =========
/lib/libc.so.6(+0x714ae)[0xb761f4ae]
/lib/libc.so.6(cfree+0x70)[0xb7623050]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb77fbff1]
/usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0xb77fc04d]
/home/alex/CB/long_ar/bin/Debug/long_ar[0x8048961]
/home/alex/CB/long_ar/bin/Debug/long_ar[0x8048bbf]
/home/alex/CB/long_ar/bin/Debug/long_ar[0x8048d36]
/lib/libc.so.6(__libc_start_main+0xe6)[0xb75c4db6]
/home/alex/CB/long_ar/bin/Debug/long_ar[0x8048791]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:03 1190984 /home/alex/CB/long_ar/bin/Debug/long_ar
0804a000-0804b000 rw-p 00001000 08:03 1190984 /home/alex/CB/long_ar/bin/Debug/long_ar
0804b000-080ac000 rw-p 00000000 00:00 0 [heap]
b7400000-b7421000 rw-p 00000000 00:00 0
b7421000-b7500000 ---p 00000000 00:00 0
b75ab000-b75ae000 rw-p 00000000 00:00 0
b75ae000-b770a000 r-xp 00000000 08:03 403253 /lib/libc-2.13.so
b770a000-b770b000 ---p 0015c000 08:03 403253 /lib/libc-2.13.so
b770b000-b770d000 r--p 0015c000 08:03 403253 /lib/libc-2.13.so
b770d000-b770e000 rw-p 0015e000 08:03 403253 /lib/libc-2.13.so
b770e000-b7711000 rw-p 00000000 00:00 0
b7711000-b772c000 r-xp 00000000 08:03 1053512 /usr/lib/libgcc_s.so.1
b772c000-b772d000 rw-p 0001a000 08:03 1053512 /usr/lib/libgcc_s.so.1
b772d000-b7751000 r-xp 00000000 08:03 403257 /lib/libm-2.13.so
b7751000-b7752000 r--p 00023000 08:03 403257 /lib/libm-2.13.so
b7752000-b7753000 rw-p 00024000 08:03 403257 /lib/libm-2.13.so
b7753000-b7830000 r-xp 00000000 08:03 1054254 /usr/lib/libstdc++.so.6.0.14
b7830000-b7834000 r--p 000dd000 08:03 1054254 /usr/lib/libstdc++.so.6.0.14
b7834000-b7835000 rw-p 000e1000 08:03 1054254 /usr/lib/libstdc++.so.6.0.14
b7835000-b783c000 rw-p 00000000 00:00 0
b7852000-b7854000 rw-p 00000000 00:00 0
b7854000-b7871000 r-xp 00000000 08:03 403295 /lib/ld-2.13.so
b7871000-b7872000 r--p 0001c000 08:03 403295 /lib/ld-2.13.so
b7872000-b7873000 rw-p 0001d000 08:03 403295 /lib/ld-2.13.so
bfd94000-bfdb5000 rw-p 00000000 00:00 0 [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]

Process returned -1 (0xFFFFFFFF) execution time : 1.678 s
Press ENTER to continue.
Должен ещё сказать, что до этого я уже реализовывал эту библиотеку. Но тогда я обошёл проблему не задумываясь, просто не освобождая память (очень срочно надо было её написать, и так проконало). Теперь же второй раз так поступать не хочу, но уже битый час сижу в попытках понять, что я делаю не так.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru