2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Выделение памяти в C++ и std::exception
Сообщение12.06.2012, 16:14 


12/06/12
34
Есть такой код, в котором выделяется память в цикле под массив и он инициализируется нулями, в зависимости от количества свободной памяти процесс прерывается с кодом -1 на определенной итерации, вопрос такой: почему собственного говоря происходит завершение процесса и как его отловить (ожидал исключение "bad_alloc", но оно не приходит в catch)? С GDB не разобрался - выдает в конце "The program is not being run".
Компилятор: gcc version 4.4.3. Target: x86_64-linux-gnu.

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>
#include <exception>

int main ()
{
  const size_t Mb = 1048576;
  const size_t size = 2048;
  int *ptr[size];
  const size_t num = 1048576;
  size_t Alloc = 0;
  try
  {
    for (size_t i = 0; i < size; i++)
    {
      ptr[i]= new int[num];
      for (size_t j = 0; j < num; j++)
        ptr[i][j] = 0;
      Alloc += num * sizeof(int);
      std::cout << i+1 << "   ptr: " << ptr << "   Alloc: " << (Alloc/Mb) <<" Mb" << std::endl;
    }
  }
  catch (std::exception &e)
  {
     std::cout << e.what() << std::endl;
  }
  return 0;
}

 

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение12.06.2012, 23:04 
Заслуженный участник


15/05/05
3445
USA
Вы выделяете память с помощью вызова из run-time (new), а исключение ловите только std::exception. Добавьте еще несколько блоков catch. Например так:
Используется синтаксис C++
  ...
  catch (std::exception &e)
  {
     std::cout << e.what() << std::endl;
  }
  catch (int e) { cout << "An int exception " << e << endl; }
  catch (...) { cout << "Вefault exception"; }
  return 0;
}

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение12.06.2012, 23:35 
Заслуженный участник


04/05/09
4587
std::bad_alloc тоже унаследован от std::exception. Не в этом дело.
Возможно, проблема в том, что программа падает в кору из-за нехватки свопа. Виртуальная память выделяется нормально, а когда она инициализируется нулями система не может выделить программе очередную страницу и программа падает по segfault.

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 00:00 
Заслуженный участник


15/05/05
3445
USA
venco в сообщении #584129 писал(а):
std::bad_alloc тоже унаследован от std::exception. Не в этом дело.
Память у ТС выделяется оператором
ptr[i]= new int[num];
Откуда тут появится std::bad_alloc?
Другое дело - если бы он запрашивал память через std::alloc.
И вообще, у него в коде от STD только std::out.

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 00:13 
Заслуженный участник


04/05/09
4587
Yuri Gendelman в сообщении #584145 писал(а):
Память у ТС выделяется оператором
ptr[i]= new int[num];
Откуда тут появится std::bad_alloc?
Дык, new как раз bad_alloc пошлёт если память выделить не получилось.

Yuri Gendelman в сообщении #584145 писал(а):
И вообще, у него в коде от STD только std::out.
Ещё std::exception и std::endl.

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 00:25 


12/06/12
34
Yuri Gendelman, благодарю, но приведенные способы не дают результата. По стандарту new в случае невозможности выделения памяти должен генерировать bad_alloc. Я просто предположил, что проблема с new, но похоже дело в чем-то другом.

-- 13.06.2012, 01:29 --

venco в сообщении #584129 писал(а):
std::bad_alloc тоже унаследован от std::exception. Не в этом дело.
Возможно, проблема в том, что программа падает в кору из-за нехватки свопа. Виртуальная память выделяется нормально, а когда она инициализируется нулями система не может выделить программе очередную страницу и программа падает по segfault.


venco, да похоже так, так как если не инициализировать массив, то всё прекрасно выделяется и процесс завершается без ошибок. Но это не очень интересно с практической точки зрения, все-таки как отследить возможность выделения памяти и её использования?

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 00:59 
Заслуженный участник
Аватара пользователя


30/01/06
72407
ilkos в сообщении #584160 писал(а):
По стандарту new в случае невозможности выделения памяти должен генерировать bad_alloc.

Ключи компилятора могут это поведение переопределить.

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 01:41 


12/06/12
34
Munin
компилировалось вот так: g++ -o test main.cpp

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 04:31 
Заслуженный участник


15/05/05
3445
USA
venco в сообщении #584154 писал(а):
Дык, new как раз bad_alloc пошлёт если память выделить не получилось.
Вопрос: bad_alloc и std::bad_alloc - это одно и то же?
Если я не использую STD и не включил в свою программу use namespace std; то какое исключение может сгенерировать new?

Насчет примера ТС, я запустил его на нашей Linux-машине (RHWS5), но он [пример] распределил 8 ГБ и никаких исключений не выдал. А времени на эксперименты не было. Завтра с утра попробую увеличить размер блока.

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 07:26 
Заслуженный участник


04/05/09
4587
Yuri Gendelman в сообщении #584245 писал(а):
venco в сообщении #584154 писал(а):
Дык, new как раз bad_alloc пошлёт если память выделить не получилось.
Вопрос: bad_alloc и std::bad_alloc - это одно и то же?
Если я не использую STD и не включил в свою программу use namespace std; то какое исключение может сгенерировать new?
Естественно, всё равно пошлёт std::bad_alloc, то, что у вас написано в using никак не влияет на библиотечные функции.
А я просто опустил префикс std::...

Yuri Gendelman в сообщении #584245 писал(а):
Насчет примера ТС, я запустил его на нашей Linux-машине (RHWS5), но он [пример] распределил 8 ГБ и никаких исключений не выдал. А времени на эксперименты не было. Завтра с утра попробую увеличить размер блока.
Надо чтобы суммарная выделяемая память превышала физическую + своп, но была меньше лимитов на виртуальную, иначе сначала будет bad_alloc.

На самом деле это большая проблема Линукса, что по умолчанию malloc() так себя ведёт - система выделяет адресного пространства больше, чем имеет физического (плюс своп). В новых кернелах есть возможность отключить эту фичу (называется memory overcommit), тогда malloc() реально будет возвращать NULL. Правда при этом каждый fork() будет требовать двойного количества памяти, что очень накладно в обычных ситуациях.

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 12:49 


12/06/12
34
venco, без вмешательства в kernel можно решить этот вопрос?

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 17:58 
Заслуженный участник


15/05/05
3445
USA
Yuri Gendelman в сообщении #584245 писал(а):
Завтра с утра попробую увеличить размер блока.

И настало утро...

1. Программа слегка модифицирована: увеличен размер выделяемого блока и два оператора вывода сделаны более (IMHO) удобочитаемыми.

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
  ...
#include <iostream>
#include <exception>

/* gcc 4.4.3. Target: x86_64-linux-gnu */

int main ()
{
  const size_t Mb = 1048576;
  const size_t size = 2048;
  int *ptr[size];
  const size_t num = 1048576*1024;    // YuG
  size_t Alloc = 0;
  try
  {
    for (size_t i = 0; i < size; i++)
    {
      ptr[i]= new int[num];
      for (size_t j = 0; j < num; j++)
        ptr[i][j] = 0;
      Alloc += num * sizeof(int);
      std::cout << i+1 << "   ptr: " << ptr[i] << "   Alloc: " << (Alloc/Mb) <<" Mb" << std::endl;   // YuG
    }
  }
  catch (std::exception &e)
  {
     std::cout << "std::exception: " << e.what() << std::endl;   // YuG
  }
  return 0;
}
 


2. Сведения о системе:

bash-3.2$ uname -a
Linux rhws5 2.6.18-308.el5 #1 SMP Fri Jan 27 17:17:51 EST 2012 x86_64 x86_64 x86_64 GNU/Linux
bash-3.2$ free
total used free shared buffers cached
Mem: 16427236 139640 16287596 0 712 12020
-/+ buffers/cache: 126908 16300328
Swap: 8159224 113772 8045452
bash-3.2$

3. компиляция:

bash-3.2$ gmake
/opt/gcc-4.1.2/bin/g++ -g -DNO_PRAGMA_ONCE -DUNIX_PLATFORM=1 -DUNIX_ENV=1 -DDEBUG -D_REENTRANT -Wno-multichar -c test.cpp -o test.o
/opt/gcc-4.1.2/bin/g++ -o test test.o -D_REENTRANT -g

Я использовал наш стандартный makefile для примеров.
Напомню, что gcc у нас - 4.1.2.

4. Результат теста:

bash-3.2$ ./test
1 ptr: 0x2aba83894010 Alloc: 4096 Mb
2 ptr: 0x2abb83896010 Alloc: 8192 Mb
3 ptr: 0x2abc83897010 Alloc: 12288 Mb
4 ptr: 0x2abd83898010 Alloc: 16384 Mb
5 ptr: 0x2abe83899010 Alloc: 20480 Mb
std::exception: St9bad_alloc
bash-3.2$

- catch сработал правильно

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 18:43 


12/06/12
34
Yuri Gendelman, попробывал с вашими ключами - результат тот же, bad_alloc нет.

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 20:05 
Заслуженный участник


04/05/09
4587
Yuri Gendelman в сообщении #584459 писал(а):
И настало утро...
Что у вас выдаёт команда ulimit -a?

 Профиль  
                  
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 21:25 
Заслуженный участник


15/05/05
3445
USA
venco в сообщении #584521 писал(а):
Что у вас выдаёт команда ulimit -a?
Код:
bash-3.2$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 134144
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 134144
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
bash-3.2$


ilkos в сообщении #584470 писал(а):
Yuri Gendelman, попробывал с вашими ключами - результат тот же, bad_alloc нет.
Мои ключи к делу не относятся. У меня с Вашими ключами
Код:
/opt/gcc-4.1.2/bin/g++ -o test test.cpp
exception тоже ловится.

У Вас нет более старого компилятора? Мы на большинстве платформ все еще используем 4.1.2, лишь кое-где - 4.2.2.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 18 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group