Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
slr00020
0 / 0 / 0
Регистрация: 11.01.2018
Сообщений: 3
1

Исключение bad_alloc

11.01.2018, 19:38. Просмотров 525. Ответов 18
Метки нет (Все метки)

Уже второй день сижу над ошибкой. За меня не нужно писать код, мне нужен просто способ устранения ошибки на словах

Пишу программу по задаче коммивояжера, когда есть две и более вершин, на которые можно пойти дальше программа считает на какую вершину выгодней перейти и пойти дальше по пути (делает поочередно обход через возможную вершину и идет до конца пути, потом возвращается и проходит через следующую вершину и когда все возможные вершины обойдены программа идет через самую выгодную вершину), если по возможному обходу встречаются еще несколько возможных вершин, то программа обходит каждый из них и т.д. Реализовал я это рекурсивно, перед тем как перейти на возможную вершину я выделяю динамическую память под еще одну матрицу и в нее копирую матрицу смежности, и перехожу на вершину, после того как обойдется граф я в матрицу возвращаю прежние значения и иду по ней дальше, проблема в том, что когда память выделяется часто программа ломается.

Есть ли какой то другой способ вернуть матрице прежние значения или можно как то сделать что бы то что произойдет в той функции по выходу из нее все изменения не будут сохранены и тогда мне не придется выделять много раз память?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.01.2018, 19:38
Ответы с готовыми решениями:

оператор new и исключение bad_alloc
Оператор new может генерировать исключение bad_alloc, определенное в заголовочном файле <new>....

Обработка исключений: проверить выделения памяти, используя исключение bad_alloc
Здравствуйте. Передо мной стоит задача: "Проверьте выделения памяти новым способом, используя...

Необработанное исключение в "0x76fd2eec" Microsoft C++: std::bad_alloc
Вот такая ошибка в VS2008, тогда как в 2013 все работает без проблем. Если есть у кого возможность...

Ошибка terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc выделение памяти
Уважаемые форумчане! Работаю над программой обработки WAV файлов, но возникла такая проблема: при...

Ошибка terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc
Есть задача: Написать программу, которая считывает текст из файла и выводит его на экран, заменив...

18
jahdjkhasjdhjah
73 / 86 / 40
Регистрация: 02.11.2017
Сообщений: 379
11.01.2018, 19:41 2
Ну пока машину времени не изобрели. Поэтому в вашем случае единственный и правильно верный способ что-то сохранить - это скопировать.
Поэтому лучше все же найти причину ошибки.
0
Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
11.01.2018, 19:44 3
Цитата Сообщение от slr00020 Посмотреть сообщение
Реализовал я это рекурсивно, перед тем как перейти на возможную вершину я выделяю динамическую память под еще одну матрицу и в нее копирую матрицу смежности, и перехожу на вершину, после того как обойдется граф я в матрицу возвращаю прежние значения и иду по ней дальше, проблема в том, что когда память выделяется часто программа ломается.
Программы ломаются при динамическом выделении памяти только тогда, когда эта памяти неправильно выделяется или освобождается (тогда и только тогда ).
Цитата Сообщение от slr00020 Посмотреть сообщение
Есть ли какой то другой способ вернуть матрице прежние значения или можно как то сделать что бы то что произойдет в той функции по выходу из нее все изменения не будут сохранены и тогда мне не придется выделять много раз память?
Многое зависит от того, как вы реализуете матрицы.
Если это класс-структура, то при передаче параметром структуры рекурсивной функции как параметра, будет передаваться созданная в стеке копия объекта структуры. После завершения вызова оригинал этой структуры в вызывающей единице изменён не будет (если, конечно, вы не прописали в прототипе функции её передачу по ссылке).
0
slr00020
0 / 0 / 0
Регистрация: 11.01.2018
Сообщений: 3
11.01.2018, 19:59  [ТС] 4
если не сложно можешь привести пример, я немного не понял как это сделать?
0
11.01.2018, 19:59
Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
11.01.2018, 20:31 5
Цитата Сообщение от slr00020 Посмотреть сообщение
если не сложно можешь привести пример, я немного не понял как это сделать?
Код
srtuct ZZZ {  
   // или class ZZZ - я надеюсь, что вы догадываетесь, что в C++ struct & class - это одно и то же
   // ...
   friend ostream& operator <<( ostream& out, const struct ZZZ& obj ) {
      // ...
   }
};

void funct( struct ZZZ z ) {
   // здесь уродуем z как Бог Черепаху ...
}

struct ZZZ z1;
cout << z1 << endl;
funct( z1 );
cout << z1 << endl; // и убеждаемся, что с z1 ничего не произошло
Добавлено через 4 минуты
В рекурсивных вычислениях (на деревьях, графах, ...) именно копирование по значению между вызовами по уровням и практикуется ... даже для простых элементарных переменных - там это ещё понятнее.
1
jahdjkhasjdhjah
73 / 86 / 40
Регистрация: 02.11.2017
Сообщений: 379
11.01.2018, 20:37 6
Цитата Сообщение от Olej Посмотреть сообщение
даже для простых элементарных переменных
При рекурсии для больших массивов (ака матриц) не самый лучший вариант копирования выделением на стеке
0
Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
11.01.2018, 20:52 7
Цитата Сообщение от jahdjkhasjdhjah Посмотреть сообщение
При рекурсии для больших массивов (ака матриц) не самый лучший вариант копирования выделением на стеке
Та ну?!

Давно копировал?
Кстати ... а про то, что ... "большие массивы (ака матрицы)" - вообще не передаются по значению, копирование в C/C++ - не слышал? Не?
0
jahdjkhasjdhjah
73 / 86 / 40
Регистрация: 02.11.2017
Сообщений: 379
11.01.2018, 20:55 8
Цитата Сообщение от Olej Посмотреть сообщение
вообще не передаются по значению
не, не слышал. Расскажите! )
И исходя из ваших утверждений и простой логики, получается, вы будете передавать один и тот же массив вглубь рекурсии, затирая его значения. Так в чем же смысл тогда всех ваших приседаний?
0
Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
11.01.2018, 21:07 9
Цитата Сообщение от jahdjkhasjdhjah Посмотреть сообщение
не, не слышал. Расскажите! )
Не стану...
Кури матчасть, сынку.
(и не нужно бездумно перетранслировать сюда глупости, которые пишут не умные авторы книжек "для чайников" и "для идиотов")
0
jahdjkhasjdhjah
73 / 86 / 40
Регистрация: 02.11.2017
Сообщений: 379
11.01.2018, 21:25 10
Цитата Сообщение от Olej Посмотреть сообщение
(и не нужно бездумно перетранслировать сюда глупости, которые пишут не умные авторы книжек "для чайников" и "для идиотов")
До вашего поста даже не знал, что они там пишут. Но вам виднее. ))
0
COKPOWEHEU
2008 / 1227 / 279
Регистрация: 09.09.2017
Сообщений: 4,990
12.01.2018, 11:40 11
Цитата Сообщение от Olej Посмотреть сообщение
Кстати ... а про то, что ... "большие массивы (ака матрицы)" - вообще не передаются по значению, копирование в C/C++ - не слышал? Не?
А ты проверял? Если бы проверил, знал бы что могут и по значению. Да-да, через стек. Стандарт такие подробности не оговаривает. Где-то в недрах форума была тема где я это проверял и выкладывал ассемблерный листинг.

Добавлено через 17 минут
не, слишком давно было. Не получается найти. Суть была в том что gcc без оптимизации передает структуру, содержащую массив, именно через стек.
1
Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
12.01.2018, 14:27 12
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Суть была в том что gcc без оптимизации передает структуру, содержащую массив
Фокус то в том, что в структуру можно завернуть только массив константного (на период компиляции) размера - что сводит ценность такой "гениальной находки" (давно, кстати, известной) ровно к нулю.
0
jahdjkhasjdhjah
73 / 86 / 40
Регистрация: 02.11.2017
Сообщений: 379
12.01.2018, 14:49 13
Цитата Сообщение от Olej Посмотреть сообщение
в структуру можно завернуть только массив константного (на период компиляции) размера
Блин, я каждый раз читаю вас, уважаемый, и поражаюсь.. Вы из какой пещеры вылезли?
Уже очень давно можно писать так:
C++
1
2
3
4
5
struct {
    char  a;
    float b;
    int   array[];
}
Единственное условие, чтобы член структуры с неизвестным размером объявлялся в ее конце.
0
COKPOWEHEU
2008 / 1227 / 279
Регистрация: 09.09.2017
Сообщений: 4,990
12.01.2018, 15:25 14
Цитата Сообщение от Olej Посмотреть сообщение
что сводит ценность такой "гениальной находки" (давно, кстати, известной) ровно к нулю.
Это не "находка" а обычное поведение Си. Все что передается в функцию передается по значению. Целочисленные переменные, адреса переменных для изменения, указатели на массивы (а что поделать если переменная, отвечающая за массив, является всего лишь адресом) и т.д.
В случае структур с динамическим массивом, массив структуре, строго говоря, не принадлежит. Он выделяется где-то на куче, а структура знает только об указателе на него. То есть при передаче в функцию, на стек честно копируются все поля, включая указатель на массив. Так что не надо дезинформировать об обязательной передаче по указателю: это не исключение из правил языка, а одно из следствий.
.
Демонстрационный пример:
Кликните здесь для просмотра всего текста
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
#include <stdio.h>
#include <inttypes.h>
 
struct Str{
  uint64_t arr1[10];
  uint64_t *arr2;
  uint64_t var; //uint64_t чтобы переменная соответствовала машинному слову - 64 бита
};
 
extern "C" void func(Str arg){
  arg.arr1[1] = 1;
  arg.arr2[1] = 1;
  arg.var = 1;
}
 
int main(){
  Str str;
  str.arr2 = new uint64_t[10];
  str.arr1[1] = 0;
  str.arr2[1] = 0;
  str.var = 0;
  
  func(str);
  printf("%lu %lu %lu\n", str.arr1[1], str.arr2[1], str.var);
  
  delete[] str.arr2;
}
Вывод:
0 1 0
Фрагмент дизассемблерного кода
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  func(str);
 785:   ff 75 f8                pushq  -0x8(%rbp)
 788:   ff 75 f0                pushq  -0x10(%rbp)
 78b:   ff 75 e8                pushq  -0x18(%rbp)
 78e:   ff 75 e0                pushq  -0x20(%rbp)
 791:   ff 75 d8                pushq  -0x28(%rbp)
 794:   ff 75 d0                pushq  -0x30(%rbp)
 797:   ff 75 c8                pushq  -0x38(%rbp)
 79a:   ff 75 c0                pushq  -0x40(%rbp)
 79d:   ff 75 b8                pushq  -0x48(%rbp)
 7a0:   ff 75 b0                pushq  -0x50(%rbp)
 7a3:   ff 75 a8                pushq  -0x58(%rbp)
 7a6:   ff 75 a0                pushq  -0x60(%rbp)
 7a9:   e8 7c ff ff ff          callq  72a <func>
Вот они все 12 сохранений данных на стек: 10 для массива, встроенного в структуру, 1 для указателя на динамический массив и 1 на переменную.
0
jahdjkhasjdhjah
73 / 86 / 40
Регистрация: 02.11.2017
Сообщений: 379
12.01.2018, 15:41 15
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Суть была в том что gcc без оптимизации передает структуру, содержащую массив, именно через стек
Сильно подозреваю, что в случае с оптимизацией, если содержимое структуры внутри функции не меняется, то передача будет по указателю. А если меняется, компиль все равно будет передавать через стек, чтобы не портить оригинальное значение.
0
Renji
2520 / 1724 / 517
Регистрация: 05.06.2014
Сообщений: 5,017
12.01.2018, 17:28 16
Цитата Сообщение от Olej Посмотреть сообщение
Кстати ... а про то, что ... "большие массивы (ака матрицы)" - вообще не передаются по значению, копирование в C/C++ - не слышал?
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Суть была в том что gcc без оптимизации передает структуру, содержащую массив, именно через стек.
А в Киеве, вы не поверите, дядька!
C++
1
2
3
4
5
typedef int Array[10];
void test(Array array)//Какие структуры, откуда? Про массивы же говорили
{
    array[0]=1;
}
0
COKPOWEHEU
2008 / 1227 / 279
Регистрация: 09.09.2017
Сообщений: 4,990
12.01.2018, 18:46 17
Цитата Сообщение от jahdjkhasjdhjah Посмотреть сообщение
Сильно подозреваю, что в случае с оптимизацией
В случае с оптимизацией может быть что угодно. Например, инлайн функции и отсутствие вообще какой-то передачи параметров.
0
jahdjkhasjdhjah
73 / 86 / 40
Регистрация: 02.11.2017
Сообщений: 379
12.01.2018, 18:58 18
В любом случае, будет генериться отдельный массив. Ну или его изменяющаяся часть. )
0
COKPOWEHEU
2008 / 1227 / 279
Регистрация: 09.09.2017
Сообщений: 4,990
12.01.2018, 19:32 19
С точки зрения программиста ничего не изменится. Будет новая копия. Если не предпринимать никаких дополнительных телодвижений, то она будет на стеке, а не в куче.
0
12.01.2018, 19:32
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.01.2018, 19:32

Ошибка terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc
Добрый день!Работаю с графами,и при больших значениях столкнулся с проблемой:ошибка в тесте...

Ошибка terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc
При выполнении программы, которая миксует функции в которых создаются типовые задачи, вылезает...

bad_alloc или bad_alloc()
Здравия желаю!:) Хотелось бы узнать, какая разница между throw bad_alloc; и throw bad_alloc();....


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

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

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