2014 dxdy logo

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

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




На страницу 1, 2  След.
 
 Выделение памяти в C++ и std::exception
Сообщение12.06.2012, 16:14 
Есть такой код, в котором выделяется память в цикле под массив и он инициализируется нулями, в зависимости от количества свободной памяти процесс прерывается с кодом -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 
Вы выделяете память с помощью вызова из 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 
std::bad_alloc тоже унаследован от std::exception. Не в этом дело.
Возможно, проблема в том, что программа падает в кору из-за нехватки свопа. Виртуальная память выделяется нормально, а когда она инициализируется нулями система не может выделить программе очередную страницу и программа падает по segfault.

 
 
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 00:00 
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 
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 
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 
Аватара пользователя
ilkos в сообщении #584160 писал(а):
По стандарту new в случае невозможности выделения памяти должен генерировать bad_alloc.

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

 
 
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 01:41 
Munin
компилировалось вот так: g++ -o test main.cpp

 
 
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 04:31 
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 
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 
venco, без вмешательства в kernel можно решить этот вопрос?

 
 
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 17:58 
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 
Yuri Gendelman, попробывал с вашими ключами - результат тот же, bad_alloc нет.

 
 
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 20:05 
Yuri Gendelman в сообщении #584459 писал(а):
И настало утро...
Что у вас выдаёт команда ulimit -a?

 
 
 
 Re: Выделение памяти в C++ и std::exception
Сообщение13.06.2012, 21:25 
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  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group