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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.73
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
#1

Оператор delete[] - C++

13.07.2010, 12:58. Просмотров 1396. Ответов 13
Метки нет (Все метки)

Код:
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
#include  <iostream>
#include <cstdlib>
#include <ctime>
#define   stop __asm nop
 
int main()
{
        int N,M;
        N=3;
        M=4;
    
        //создаем указатель на одномерный динамический массив(1) с размерностями N*M
        int*pointer2dyn_arr=new int[N*M];
 
        //указатель на новый дин. массив(2), созданный для удобства обращения к элементам     одномерного массива
        int**pp2dyn_arr=new int *[N]; 
        
        //заполняем массив 2
        for(int i=0;i<N;i++)        
        {
            pp2dyn_arr[i]=pointer2dyn_arr+i*M;
        }
        
        //устанавливаем стартовую точку последовательности, которую генерирует rand()
        srand((unsigned)time(0));
        //заполняем массив 1
        for (int i=0;i<(N*M);i++)
        {
            pp2dyn_arr[0][i]=rand()%89+10;  //от 10 до 99
            if (i%M==0)std::cout<<'\n';
            std::cout<<pp2dyn_arr[0][i]<<' ';
            
        }
 
////  сумма элементов.
        int sum1=0; 
        for(int i= 0; i < (N*M) ; ++i)  
        {
            sum1+=pp2dyn_arr[0][i];
        }
        std::cout<<'\n';
    
    //Задание2а. В сформированном массиве отсортируйте каждую строку по
    //убыванию значений. Используйте сортировку "выбором"
 
        for(int k=0;k<N;++k) //пробегаем по строкам
        {
            for(int i = 0; i < (M) ; i++) //сортируем 
            {   
                int*max_el=pointer2dyn_arr;
                int*next_el=pointer2dyn_arr+1;
                for(int j=i+1;j<M;j++)  //пробегаем по ячейкам
                {
                    if(*next_el>*max_el)max_el=next_el;
                    next_el++;
                }
                int tmp=*max_el;
                *max_el=*pointer2dyn_arr;
                *pointer2dyn_arr=tmp;
                pointer2dyn_arr++;  
            }
        }
        
    //вывод отсортированных значений
        for (int i=0;i<(N*M);i++)
            {
                if (i%M==0)std::cout<<'\n';
                std::cout<<pp2dyn_arr[0][i]<<' ';
            }
        stop
    
        delete[] pointer2dyn_arr;
        pointer2dyn_arr=0;
        //delete[] pp2dyn_arr;
        //pp2dyn_arr=0;
        
        stop
return 0;
}
Во время выполнения выдает ошибку на 72 строке:
Debug Assertion Failed!
...
Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
...
вот что пишет в окне отладка:
Пр1сем.exe привело в действие точку остановка
HEAP[Пр1сем.exe]: Invalid address specified to RtlValidateHeap( 00520000, 005249A0 )
ОС Windows инициировала точку останова в Пр1сем.exe.

Это может быть вызвано повреждением кучи и указывает на ошибку в Пр1сем.exe или в одной из загруженных им DLL.

Возможной причиной так же может быть нажатие пользователем клавиши F12, когда фокус принадлежит Пр1сем.exe
Помогите, пожалуйста, разобраться с ошибкой.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт С++
7958 / 4720 / 319
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
13.07.2010, 14:09     Оператор delete[] #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
#include  <iostream>
#include <cstdlib>
#include <ctime>
#define   stop __asm nop
 
int main()
{
                int N,M;
                N=3;
                M=4;
        
                //создаем указатель на одномерный динамический массив(1) с размерностями N*M
                int*pointer2dyn_arr=new int[N*M];
 
                //указатель на новый дин. массив(2), созданный для удобства обращения к элементам     одномерного массива
                int**pp2dyn_arr=new int *[N]; 
                
                //заполняем массив 2
                /*for(int i=0;i<N;i++)
                    pp2dyn_arr[i]=new int[N];*/
                for(int i=0;i<N;i++)            
                {
                        pp2dyn_arr[i]=pointer2dyn_arr+i*M;
                }
                
                //устанавливаем стартовую точку последовательности, которую генерирует rand()
                srand((unsigned)time(0));
                //заполняем массив 1
                for (int i=0;i<(N*M);i++)
                {
                        pp2dyn_arr[0][i]=rand()%89+10;  //от 10 до 99
                        if (i%M==0)std::cout<<'\n';
                        std::cout<<pp2dyn_arr[0][i]<<' ';
                        
                }
 
////  сумма элементов.
                int sum1=0; 
                for(int i= 0; i < (N*M) ; ++i)  
                {
                        sum1+=pp2dyn_arr[0][i];
                }
                std::cout<<'\n';
        
        //Задание2а. В сформированном массиве отсортируйте каждую строку по
        //убыванию значений. Используйте сортировку "выбором"
 
                for(int k=0;k<N;++k) //пробегаем по строкам
                {
                        for(int i = 0; i < (M) ; i++) //сортируем 
                        {       
                                int*max_el=pointer2dyn_arr;
                                int*next_el=pointer2dyn_arr+1;
                                for(int j=i+1;j<M;j++)  //пробегаем по ячейкам
                                {
                                        if(*next_el>*max_el)max_el=next_el;
                                        next_el++;
                                }
                                int tmp=*max_el;
                                *max_el=*pointer2dyn_arr;
                                *pointer2dyn_arr=tmp;
                                pointer2dyn_arr++;      
                        }
                }
                
        //вывод отсортированных значений
                for (int i=0;i<(N*M);i++)
                        {
                                if (i%M==0)std::cout<<'\n';
                                std::cout<<pp2dyn_arr[0][i]<<' ';
                        }
                stop
                delete[] pp2dyn_arr;
                //pointer2dyn_arr=0;
                //delete[] pp2dyn_arr;
                //pp2dyn_arr=0;
                
                stop
return 0;
}
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
13.07.2010, 22:36  [ТС]     Оператор delete[] #3
Цитата Сообщение от Lavroff Посмотреть сообщение
Ну вот так конечно работает... Но не полностью чистит память...
Если в моем примере удалить 72 строку(на которой появляется ошибка), то тоже все работает,
но не полностью чистит память...

Ошибка то в чем???
Nick Alte
Эксперт С++
1605 / 997 / 118
Регистрация: 27.09.2009
Сообщений: 1,923
Завершенные тесты: 1
13.07.2010, 22:54     Оператор delete[] #4
Просто любопытства ради - что случается, если сначала удалять pp2dyn_arr?
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
13.07.2010, 23:03  [ТС]     Оператор delete[] #5
Цитата Сообщение от Nick Alte Посмотреть сообщение
Просто любопытства ради - что случается, если сначала удалять pp2dyn_arr?
То же самое.
Ошибку выдает на этой же строке
C++
1
delete[] pointer2dyn_arr;
Bazan
22 / 22 / 0
Регистрация: 15.04.2009
Сообщений: 100
13.07.2010, 23:05     Оператор delete[] #6
Цитата Сообщение от st_dent Посмотреть сообщение
Если в моем примере удалить 72 строку(на которой появляется ошибка), то тоже все работает,
Ошибка то в чем???
В том, что в строке №60 операцией ++ ты не добавляешь 1 к значению pointer2dyn_arr, а изменяешь адрес, поскольку эта переменная инициализирована как указатель. Эта строчка должна выглядеть так:
*pointer2dyn_arr+=1;
еще попробуй
*pointer2dyn_arr++;
но этот вариант у меня не работает в отличие от первого.
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
13.07.2010, 23:15  [ТС]     Оператор delete[] #7
Цитата Сообщение от Bazan Посмотреть сообщение
В том, что в строке №60 операцией ++ ты не добавляешь 1 к значению pointer2dyn_arr, а изменяешь адрес, поскольку эта переменная инициализирована как указатель.
Там и не надо изменять значение. Там указатель перемещается на следующий элемент массива.
Crudelis
Шаровик затейник
670 / 412 / 13
Регистрация: 06.05.2010
Сообщений: 1,109
13.07.2010, 23:29     Оператор delete[] #8
pointer2dyn_arr=0; после удаления самого pointer2dyn_arr зачем? если его после удаления нет
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
13.07.2010, 23:46  [ТС]     Оператор delete[] #9
Bazan, Спасибо. Натолкнул на мысль.В данном случае, следует вернуть указатель на место(т.е. на начало массива).
добавить pointer2dyn_arr-=(N*M); на 63 строку
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
#include  <iostream>
#include <cstdlib>
#include <ctime>
#define   stop __asm nop
 
int main()
{
                int N,M;
                N=3;
                M=4;
        
                //создаем указатель на одномерный динамический массив(1) с размерностями N*M
                int*pointer2dyn_arr=new int[N*M];
 
                //указатель на новый дин. массив(2), созданный для удобства обращения к элементам     одномерного массива
                int**pp2dyn_arr=new int *[N]; 
                
                //заполняем массив 2
                for(int i=0;i<N;i++)            
                {
                        pp2dyn_arr[i]=pointer2dyn_arr+i*M;
                }
                
                //устанавливаем стартовую точку последовательности, которую генерирует rand()
                srand((unsigned)time(0));
                //заполняем массив 1
                for (int i=0;i<(N*M);i++)
                {
                        pp2dyn_arr[0][i]=rand()%89+10;  //от 10 до 99
                        if (i%M==0)std::cout<<'\n';
                        std::cout<<pp2dyn_arr[0][i]<<' ';
                        
                }
 
////  сумма элементов.
                int sum1=0; 
                for(int i= 0; i < (N*M) ; ++i)  
                {
                        sum1+=pp2dyn_arr[0][i];
                }
                std::cout<<'\n';
        
        //Задание2а. В сформированном массиве отсортируйте каждую строку по
        //убыванию значений. Используйте сортировку "выбором"
 
                for(int k=0;k<N;++k) //пробегаем по строкам
                {
                        for(int i = 0; i < (M) ; i++) //сортируем 
                        {       
                                int*max_el=pointer2dyn_arr;
                                int*next_el=pointer2dyn_arr+1;
                                for(int j=i+1;j<M;j++)  //пробегаем по ячейкам
                                {
                                        if(*next_el>*max_el)max_el=next_el;
                                        next_el++;
                                }
                                int tmp=*max_el;
                                *max_el=*pointer2dyn_arr;
                                *pointer2dyn_arr=tmp;
                                pointer2dyn_arr++;      
                        }
                }
                pointer2dyn_arr-=(N*M);
        //вывод отсортированных значений
                for (int i=0;i<(N*M);i++)
                        {
                                if (i%M==0)std::cout<<'\n';
                                std::cout<<pp2dyn_arr[0][i]<<' ';
                        }
                stop
        
                delete[] pointer2dyn_arr;
                pointer2dyn_arr=0;
                //delete[] pp2dyn_arr;
                //pp2dyn_arr=0;
                
                stop
return 0;
}


Как в данном случае можно проверить полностью ли освободилась память?

Добавлено через 11 минут
Цитата Сообщение от Crudelis Посмотреть сообщение
pointer2dyn_arr=0; после удаления самого pointer2dyn_arr зачем? если его после удаления нет
delete не удаляет указатель.Он освобождает блок памяти, адрес которого содержится в указателе. Т.к. значение адреса все еще хранится в указателе, безопаснее его обнулить.
easybudda
Эксперт С++
9455 / 5468 / 927
Регистрация: 25.07.2009
Сообщений: 10,495
13.07.2010, 23:58     Оператор delete[] #10
Цитата Сообщение от st_dent Посмотреть сообщение
Там указатель перемещается на следующий элемент массива.
так в этом и проблема. после изменения значения указателя применять к нему операцию delete [] как-то не корректно. сделайте копию указателя и увеличивайте её значение. тогда указатель, для которого выделялась память оператором new [] будет пригоден и для оператора delete []
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
14.07.2010, 00:28  [ТС]     Оператор delete[] #11
Цитата Сообщение от easybudda Посмотреть сообщение
так в этом и проблема. после изменения значения указателя применять к нему операцию delete [] как-то не корректно. сделайте копию указателя и увеличивайте её значение. тогда указатель, для которого выделялась память оператором new [] будет пригоден и для оператора delete []
вот так корректно будет память освобождена?
C++
1
2
3
4
5
6
7
8
//некий код
int*pointer2dyn_arr=new int[N*M];
pointer2dyn_arr++;
pointer2dyn_arr++;
pointer2dyn_arr=pointer2dyn_arr-2;
delete[] pointer2dyn_arr;
pointer2dyn_arr=0;
//ещё код
easybudda
Эксперт С++
9455 / 5468 / 927
Регистрация: 25.07.2009
Сообщений: 10,495
14.07.2010, 00:33     Оператор delete[] #12
Цитата Сообщение от st_dent Посмотреть сообщение
вот так корректно будет память освобождена?
возможно, но я бы лучше не так делал...
C++
1
2
3
4
5
6
7
8
...
int*pointer2dyn_arr=new int[N*M];
int *pointer2dyn_arr_copy = pointer2dyn_arr;
pointer2dyn_arr_copy += 100500;
...
delete[] pointer2dyn_arr;
pointer2dyn_arr=0;
...
st_dent
64 / 64 / 3
Регистрация: 05.07.2010
Сообщений: 219
14.07.2010, 01:55  [ТС]     Оператор delete[] #13
Цитата Сообщение от easybudda Посмотреть сообщение
возможно, но я бы лучше не так делал...
И всё-таки, почему бы вы так не делали?
Личный опыт? Поделитесь, пожалуйста.
Авторитетные источники? Поделитесь,пожалуйста.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.07.2010, 02:22     Оператор delete[]
Еще ссылки по теме:

Оператор delete C++
C++ оператор delete
Оператор delete в деструкторе C++
C++ Нужно ли тут вызывать оператор delete
C++ Хочу понять когда можно делать оператор delete

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
easybudda
Эксперт С++
9455 / 5468 / 927
Регистрация: 25.07.2009
Сообщений: 10,495
14.07.2010, 02:22     Оператор delete[] #14
Цитата Сообщение от st_dent Посмотреть сообщение
И всё-таки, почему бы вы так не делали?
Личный опыт? Поделитесь, пожалуйста.
Авторитетные источники? Поделитесь,пожалуйста.
Скорее личное мнение, основанное от части на опыте, от части на примерах из книг... Если указатель используется для выделения какого-то участка памяти, то лучше его значение не менять, пока в выделенной памяти нужда не отпадёт и она не будет освобождена. Так по крайней мере от подобных ошибок себя убережёте...
Yandex
Объявления
14.07.2010, 02:22     Оператор delete[]
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru