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

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

Войти
Регистрация
Восстановить пароль
 
Whitelake
0 / 0 / 0
Регистрация: 29.10.2014
Сообщений: 8
#1

Утечки памяти при использовании new/delete для двумерных массивов - C++

29.10.2014, 15:04. Просмотров 530. Ответов 10
Метки нет (Все метки)

Добрый день.

Суть в том, что есть несколько функций, получающих на вход и возвращающих двумерные массивы. Реализация передачи массивов ясна из кода ниже. Функции вызываются одна из-под другой.

Отслеживание утечек памяти делаю с помощью _CrtDumpMemoryLeaks() перед завершением в main.
Утечки обнаруживаются в местах, где выделяется память под массив, который потом будет заполняться вызовом другой функции. В приведённом коде, например, ругнётся на строчки 3 и 6 файла F0.cpp.

main.cpp:
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
int main (void)
{
    double **U = new double*[9];
    for(i = 0; i < 9; i++)
    {
        U[i] = new double[N];
    }
 
    // Делаем что-то с U
 
    while ( //условие )
    {
        U = F0(U);      
    }
 
    _CrtDumpMemoryLeaks();
 
    for(i=0; i<9; i++)
    {
        delete []U[i]; U[i] = 0;
    }
    delete []U; U = 0;
 
    return 0;
}
F0.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
double **F0(double **U)
{
    double **L = new double*[9];
    for(i = 0; i < 9; i++)
    {
        L[i] = new double[N];
    }
 
    L = F1(U);
    U = //преобразования L
 
    for(i=0; i<9; i++)
    {
        delete []L[i]; L[i] = 0;
    }
    delete []L; L = 0;
 
    return U;
}
F1.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
double **F1(double **U)
{
    double **L = new double*[9];
    for(i = 0; i < 9; i++)
    {
        L[i] = new double[N];
    }
 
    //...
 
    return L;
 
    for(i=0; i<9; i++)
    {
        delete []L[i]; L[i] = 0;
    }
    delete []L; L = 0;
}
В целом, всё работает корректно, но при достаточно длинном цикле в main, через некоторое время вылетает с ошибкой типа "Unhandled exception at 0x76e7c42d in 123.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x003be460..".
Ошибка, вероятно, в выделении/освобождении памяти при работе с вложенными функциями, но ничего в голову не приходит. Подскажите, пожалуйста.

Заранее благодарен.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.10.2014, 15:04
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Утечки памяти при использовании new/delete для двумерных массивов (C++):

Динамическое выделение памяти. Использование функций для обработки двумерных массивов - C++
не понимаю что делаю хотя задание такое 1.2. Постановка задачи Задача 1. Разработать алгоритм и программу выполняющую следующие...

Какие есть виды массивов (кроме одномерных, двумерных и двумерных ступенчатых массивов)? - C++
Какие есть виды массивов (кроме одномерных, двумерных и двумерных ступенчатых массивов)? И почему такая вот запись является &quot;чуть&quot;...

Ошибка при использовании new[] / delete[] - C++
Здравствуйте. Пишу учебную программу, моделирующую движение лифта (если кто учебник Дейтелов читал, тот поймет :) ). Для начала приведу...

Ошибка при использовании delete - C++
И снова здравствуйте! Пишу раз третий.Я уже готов убицца ап сцену изза этого delete.Я не понимаю что не так делаю: class CMenu { ...

Ошибка при использовании оператора delete в Visual Studio 2010 - C++
Изучаю указатели в C++. Есть следующий код: #include &lt;iostream&gt; #include &lt;locale&gt; using namespace std; int main() { ...

new и delete при освобождении памяти - C++
Здравствуйте. Скажите, пожалуйста что я неправильно делаю. При освобождении памяти. Выделяем память: char **VIRTUAL = NULL; if...

10
Tulosba
:)
Эксперт С++
4705 / 3240 / 297
Регистрация: 19.02.2013
Сообщений: 9,046
29.10.2014, 15:27 #2
в F0.cpp в 9 строке теряется доступ (остается висеть в памяти) к тому что было выделено в 3 и 6 строках.
0
Whitelake
0 / 0 / 0
Регистрация: 29.10.2014
Сообщений: 8
29.10.2014, 18:29  [ТС] #3
Цитата Сообщение от Tulosba Посмотреть сообщение
в F0.cpp в 9 строке теряется доступ (остается висеть в памяти) к тому что было выделено в 3 и 6 строках.
Спасибо.
А как в таком случае вернуть результат выполнения F1 в F0, так чтобы потом эту память очистить?
0
alsav22
5437 / 4832 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2014, 18:48 #4
Смысл, вот этого куска, в чём?

Цитата Сообщение от Whitelake Посмотреть сообщение
C++
1
2
3
4
5
6
7
return L;
for(i=0; i<9; i++)
{
    delete []L[i]; L[i] = 0;
}
delete []L; L = 0;
}
0
Whitelake
0 / 0 / 0
Регистрация: 29.10.2014
Сообщений: 8
29.10.2014, 18:59  [ТС] #5
Не нужно освобождать память, выделенную под возвращаемую переменную? При return она освобождается автоматически?
На самом деле, подобные конструкции -- результат попыток решить проблему методом тыка, ибо всё что мог уже попробовал, а от утечек избавиться не удаётся.

Вы уж не судите строго: переношу код на практически новый для меня язык.
0
alsav22
5437 / 4832 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2014, 19:05 #6
Цитата Сообщение от Whitelake Посмотреть сообщение
Не нужно освобождать память, выделенную под возвращаемую переменную?
Если return стоит перед освобождением памяти, то как туда код сможет дойти?

Добавлено через 3 минуты
Цитата Сообщение от Whitelake Посмотреть сообщение
На самом деле, подобные конструкции -- результат попыток решить проблему методом тыка, ибо всё что мог уже попробовал, а от утечек избавиться не удаётся.
Проблема, по-моему, в том, что код не продуман. Непонятно, зачем там, вообще, эти вызовы функций с передачами массивов? Без них, разве, нельзя обойтись? Задача какая?
0
Whitelake
0 / 0 / 0
Регистрация: 29.10.2014
Сообщений: 8
29.10.2014, 19:16  [ТС] #7
Вызовы функций с передачами массивов нужны, так как очень желательно сохранить структуру программы, написанной на Фортране... Наверное, это не очень правильно, но это уже вопрос идеологического плана.
А проблему хотелось бы решить в рамках существующей реализации: нужно правильно выделить память под массив, записать в него результат выполнения функции и освободить память.
0
alsav22
5437 / 4832 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2014, 20:38 #8
Цитата Сообщение от Whitelake Посмотреть сообщение
А проблему хотелось бы решить в рамках существующей реализации: нужно правильно выделить память под массив, записать в него результат выполнения функции и освободить память.
Чтобы конкретное что-либо посоветовать, нужно больше кода видеть. По выложенным кускам мало что понятно.

Добавлено через 1 час 15 минут
А общий совет: передавайте по ссылке, тогда и возвращать ничего не нужно.
0
Whitelake
0 / 0 / 0
Регистрация: 29.10.2014
Сообщений: 8
29.10.2014, 21:01  [ТС] #9
Цитата Сообщение от alsav22 Посмотреть сообщение
А общий совет: передавайте по ссылке, тогда и возвращать ничего не нужно.
Это было бы хорошо, но что-то я совсем не представляю, как сделать передачу по ссылке двумерного массива...
0
alsav22
5437 / 4832 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2014, 22:26 #10
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Whitelake Посмотреть сообщение
как сделать передачу по ссылке двумерного массива...
Так же, как одномерного.

Добавлено через 58 минут
Если в функциях действия только с содержимым массива:
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>
using namespace std;
 
void F0(double **U);
void F1(double **U);
 
int N = 3;
int M = 4;
 
int main (void)
{
    double **U = new double*[N];
    for(int i = 0; i < N; i++)
    {
        U[i] = new double[M];
        for (int j = 0; j < M; ++j)
            U[i][j] = j;
    }
    
    cout << "main" << endl; 
    for(int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    F0(U);
    
    cout << "main after F0" << endl; 
    for(int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    for(int i=0; i<N; i++)
        delete [] U[i]; 
    delete [] U;
   
    cout << _CrtDumpMemoryLeaks() << endl;
    return 0;
}
 
void F0(double **U)
{
    for(int i = 0; i < N; i++)
        for (int j = 0; j < M; ++j)
           ++(U[i][j]);
        
    cout << "F0" << endl;
    for(int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    F1(U);
    
    cout << "F0 after F1" << endl;
    for(int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
}
 
void F1(double **U)
{
    for(int i = 0; i < N; i++)
        for (int j = 0; j < M; ++j)
           ++(U[i][j]);
}
Если действия и с указателем (перевыделение памяти):
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
#include <iostream>
using namespace std;
 
void F0(double **&U);
void F1(double **&U);
 
int N = 3;
int M = 4;
 
int A = 5;
int B = 6;
 
int main (void)
{
    double **U = new double*[N];
    for(int i = 0; i < N; i++)
    {
        U[i] = new double[M];
        for (int j = 0; j < M; ++j)
            U[i][j] = j;
    }
    
    cout << "main" << endl; 
    for(int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    F0(U);
    
    cout << "main after F0" << endl; 
    for(int i = 0; i < A; i++)
    {
        for (int j = 0; j < B; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    for(int i=0; i<A; i++)
        delete [] U[i]; 
    delete [] U;
   
    cout << _CrtDumpMemoryLeaks() << endl;
    return 0;
}
 
void F0(double **&U)
{
    for(int i = 0; i < N; i++)
        for (int j = 0; j < M; ++j)
           ++(U[i][j]);
    
    cout << "F0" << endl;   
    for(int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    F1(U);
    
    cout << "F0 after F1" << endl;
    for(int i = 0; i < A; i++)
    {
        for (int j = 0; j < B; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
}
 
void F1(double **&U)
{
    for(int i = 0; i < N; i++)
        delete [] U[i]; 
    delete [] U;
    
    U = new double*[A];
    for(int i = 0; i < A; i++)
    {
        U[i] = new double[B];
        for (int j = 0; j < B; ++j)
            U[i][j] = j;
    }
}
Добавлено через 16 минут
Или так:
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
#include <iostream>
using namespace std;
 
struct size
{
    int n;
    int m;
};
 
size F0(double **&U);
size F1(double **&U);
 
int N = 3;
int M = 4;
 
int main (void)
{
    double **U = new double*[N];
    for(int i = 0; i < N; i++)
    {
        U[i] = new double[M];
        for (int j = 0; j < M; ++j)
            U[i][j] = j;
    }
    
    cout << "main" << endl; 
    for(int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    size s = F0(U);
    cout << "main after F0" << endl; 
    for(int i = 0; i < s.n; i++)
    {
        for (int j = 0; j < s.m; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    for(int i = 0; i < s.n; i++)
        delete [] U[i]; 
    delete [] U;
   
    cout << _CrtDumpMemoryLeaks() << endl;
    return 0;
}
 
size F0(double **&U)
{
    for(int i = 0; i < N; i++)
        for (int j = 0; j < M; ++j)
           ++(U[i][j]);
    
    cout << "F0" << endl;   
    for(int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    
    size s = F1(U);
    
    cout << "F0 after F1" << endl;
    for(int i = 0; i < s.n; i++)
    {
        for (int j = 0; j < s.m; ++j)
           cout << U[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
 
    return s;
}
 
size F1(double **&U)
{
    for(int i = 0; i < N; i++)
        delete [] U[i]; 
    delete [] U;
 
    size s = {5, 6};
    
    U = new double*[s.n];
    for(int i = 0; i < s.n; i++)
    {
        U[i] = new double[s.m];
        for (int j = 0; j < s.m; ++j)
            U[i][j] = j;
    }
 
    return s;
}
1
Whitelake
0 / 0 / 0
Регистрация: 29.10.2014
Сообщений: 8
30.10.2014, 00:29  [ТС] #11
alsav22, большое спасибо за помощь.
Я переделал всё так, чтобы все "вложенные" функции были void, то есть преобразовывали получаемый массив в соответствии с первым из предложенных вариантов. Нужно было сразу об этом задуматься: задача такова, что все передаваемые и возвращаемые массивы имеют одинаковые размерности.
С памятью теперь всё нормально.

Ещё раз благодарю.
0
30.10.2014, 00:29
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.10.2014, 00:29
Привет! Вот еще темы с ответами:

Ошибка при освобождении памяти (delete) - C++
Здравствуйте! Есть массив lines, созданный вот так : int *line = new int ; Потом, пытаюсь его удалить и пересоздать : delete...

Использование двумерных массивов при обращении к объектам классов - C++
Проблема в программе, если будет нужно, напишу подробности программы. Компилятор ругается на эту строчку printf(&quot;%d&quot;,M); Таким...

Ошибка с delete при удалении памяти из-под строки - C++
strngbad.h // strngbad.h -- flawed string class definition #include &lt;iostream&gt; #ifndef STRNGBAD_H_ #define STRNGBAD_H_ class...

Универсальная функция для приема разных двумерных массивов - C++
В программе у меня много двумерных массивом разной размерности. Мне нужна одна функция (общая) чтобы работала на все массивы. Функция...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

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