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

Ошибка при освобождении памяти - 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 минуты вот нужный отрывок class List { struct Elem {
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 <string> using namespace std; template <typename InType> class Shablon1 { public:
C++ необходимо найти максимальный элемент матрицы используя несколько потоков С++ Добрый день программисты, необходимо выполнить поиск наименьшего элемента матрицы используя количество потоков равное количеству строк данной матрицы. Каждый поток находит минимальный элемент своей строки и записывает его в одномерный массив. а потом оттуда находиться минимальный элемент. кто сможет помочь с поставленной задачей? подробнее

Показать сообщение отдельно
AlexSome
0 / 0 / 0
Регистрация: 14.01.2012
Сообщений: 6
14.01.2012, 15:07  [ТС]     Ошибка при освобождении памяти
greeezz, спасибо! Наконец-то я нашёл ошибку! А теперь всё по порядку:

функция pow (double, double); а вы используете как int и unsigned int
Я знаю, что это не совсем верно, но, тем не менее, одним из вариантов является такое использование:
double pow ( double base, int exponent );
а перевод потом из double в int меня устраивает.
в строке 64 for (unsigned int i=1; i<=max_value; i++) выход за пределы массива
Вот! Вот это место, из-за которого я сидел всю ночь! Как всегда, одну единичку не доглядел - и сиди мучайся Только я устранил не так, как вы предложили, а наоборот,
C++
1
base = new unsigned int [max_value + 1]; // + 1 для первого разряда (размера)
так как у меня разряд адреса (0й элемент моего массива) вполне может хранить значение <= 65535. Только всё равно для меня остаётся загадкой: если я всего-навсего 1 раз вылазил за пределы выделенной памяти - почему оно не ругалось при этом обращении, а именно потом при освобождении памяти? Тем не менее, теперь работает
Я вам рекомендую отложить код в сторону. НАРИСОВАТЬ на листочке ход вашей программы. и описать основные узлы и написать программу заново.
Я уже делал библиотеку длинной арфиметики, как я уже писал выше. Я пока что даже не успел дойти до особых сложностей, и ещё нет смысла ничего рисовать т.к. у меня всё прекрасно в голове укладывается. Как видите, вся проблема в том одном недовыделенном элементе
Кстати раз уже вы решили делать с использованием классов то зачем вы из функции в функцию "таскаете" размер вашего числа ???
Логичный совет. Я выбрал именно такую реализацию, т.к. есть идея потом сделать также вариацию без классов, а только используя функции. Если бы я ввёл дополнительную переменную, то я практически отрезал бы себе такую возможность, или пришлось бы создавать структуры (почему бы тогда не использовать те же классы).
сейчас например функция
void number::clear_nulls()
не имеет понятия какая новая длина вашего числа.
под нулевым индексом в массиве у вас там 65535.
Она не имеет понятия только когда работает после input'a, т.к. input по умолчанию задаёт максимальный размер числа.
Еще если вы хотите все сделать самостоятельно почему бы не реализовать связанный список ?
Для этого вам для удобства понадобится два класса.
1 - для описания (объекта) элемента списка.
2 - для манипуляции с (объектами) элементами в списке.
По-моему в таком случае будет намного сложнее писать функции длинной арифметики. Хотя это так, навскидку. Но в любом случае, связный список будет потреблять больше памяти (за счёт своих указателей) и выполняться, скорее всего, медленнее.

Спасибо за пример кода. Правда я там по-своему исправил, но, в любом случае, спасибо за помощь!

Вот теперь мой код:
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#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();
    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()
{
    delete []base; // просто очищаем память
}
 
number::number(const number& obj)
{
    base = new unsigned int [obj.base[0] + 1]; // выделяем столько же памяти (1 для разряда размера)
    base[0] = obj.base[0];
    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 + 1]; // + 1 для первого разряда (размера)
    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 < max_value * max_digits) // работа до тех пор, пока считанный символ - цифра, и пока число не превысит максимальный размер
    {
        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); // считывание следующего символа
    }
    if (signs_count > 0) // если ввели хоть одну цифру
    {
        base[0] = (signs_count - 1) / max_digits + 1; // размер высчитывается в зависимости от введённыих символов (для экономии времени при очистке нулей)
        this->clear_nulls(); // очищаем незначащие нули
    }
    else // иначе число считается нулём
    {
        delete []base; // очищаем ранее выделенную под число память
        base = new unsigned int [2];
        base[0] = 1;
        base[1] = 0;
    }
}
 
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;
}
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru