Ошибка std bad alloc

What is the C++ Standard specified behavior of new in c++?

The usual notion is that if new operator cannot allocate dynamic memory of the requested size, then it should throw an exception of type std::bad_alloc.
However, something more happens even before a bad_alloc exception is thrown:

C++03 Section 3.7.4.1.3: says

An allocation function that fails to allocate storage can invoke the currently installed new_handler(18.4.2.2), if any. [Note: A program-supplied allocation function can obtain the address of the currently installed new_handler using the set_new_handler function (18.4.2.3).] If an allocation function declared with an empty exception-specification (15.4), throw(), fails to allocate storage, it shall return a null pointer. Any other allocation function that fails to allocate storage shall only indicate failure by throw-ing an exception of class std::bad_alloc (18.4.2.1) or a class derived from std::bad_alloc.

Consider the following code sample:

#include <iostream>
#include <cstdlib>

// function to call if operator new can't allocate enough memory or error arises
void outOfMemHandler()
{
    std::cerr << "Unable to satisfy request for memoryn";

    std::abort();
}

int main()
{
    //set the new_handler
    std::set_new_handler(outOfMemHandler);

    //Request huge memory size, that will cause ::operator new to fail
    int *pBigDataArray = new int[100000000L];

    return 0;
}

In the above example, operator new (most likely) will be unable to allocate space for 100,000,000 integers, and the function outOfMemHandler() will be called, and the program will abort after issuing an error message.

As seen here the default behavior of new operator when unable to fulfill a memory request, is to call the new-handler function repeatedly until it can find enough memory or there is no more new handlers. In the above example, unless we call std::abort(), outOfMemHandler() would be called repeatedly. Therefore, the handler should either ensure that the next allocation succeeds, or register another handler, or register no handler, or not return (i.e. terminate the program). If there is no new handler and the allocation fails, the operator will throw an exception.

What is the new_handler and set_new_handler?

new_handler is a typedef for a pointer to a function that takes and returns nothing, and set_new_handler is a function that takes and returns a new_handler.

Something like:

typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();

set_new_handler’s parameter is a pointer to the function operator new should call if it can’t allocate the requested memory. Its return value is a pointer to the previously registered handler function, or null if there was no previous handler.

How to handle out of memory conditions in C++?

Given the behavior of newa well designed user program should handle out of memory conditions by providing a proper new_handlerwhich does one of the following:

Make more memory available: This may allow the next memory allocation attempt inside operator new’s loop to succeed. One way to implement this is to allocate a large block of memory at program start-up, then release it for use in the program the first time the new-handler is invoked.

Install a different new-handler: If the current new-handler can’t make any more memory available, and of there is another new-handler that can, then the current new-handler can install the other new-handler in its place (by calling set_new_handler). The next time operator new calls the new-handler function, it will get the one most recently installed.

(A variation on this theme is for a new-handler to modify its own behavior, so the next time it’s invoked, it does something different. One way to achieve this is to have the new-handler modify static, namespace-specific, or global data that affects the new-handler’s behavior.)

Uninstall the new-handler: This is done by passing a null pointer to set_new_handler. With no new-handler installed, operator new will throw an exception ((convertible to) std::bad_alloc) when memory allocation is unsuccessful.

Throw an exception convertible to std::bad_alloc. Such exceptions are not be caught by operator new, but will propagate to the site originating the request for memory.

Not return: By calling abort or exit.

Defined in header <new>

class bad_alloc;

std::bad_alloc is the type of the object thrown as exceptions by the allocation functions to report failure to allocate storage.

std-bad alloc-inheritance.svg

Inheritance diagram

Contents

  • 1 Member functions
  • 2 std::bad_alloc::bad_alloc
    • 2.1 Parameters
  • 3 std::bad_alloc::operator=
    • 3.1 Parameters
    • 3.2 Return value
  • 4 std::bad_alloc::what
    • 4.1 Parameters
    • 4.2 Return value
    • 4.3 Notes
  • 5 Inherited from std::exception
    • 5.1 Member functions
    • 5.2 Example
    • 5.3 See also

[edit] Member functions

constructs a new bad_alloc object
(public member function)
replaces the bad_alloc object
(public member function)
returns the explanatory string
(public member function)

std::bad_alloc::bad_alloc

(1)

bad_alloc() throw();

(until C++11)

bad_alloc() noexcept;

(since C++11)
(2)

bad_alloc( const bad_alloc& other ) throw();

(until C++11)

bad_alloc( const bad_alloc& other ) noexcept;

(since C++11)

Constructs a new bad_alloc object with an implementation-defined null-terminated byte string which is accessible through what().

1) Default constructor.

2) Copy constructor. If *this and other both have dynamic type std::bad_alloc then std::strcmp(what(), other.what()) == 0. (since C++11)

Parameters

other another exception object to copy

std::bad_alloc::operator=

bad_alloc& operator=( const bad_alloc& other ) throw();

(until C++11)

bad_alloc& operator=( const bad_alloc& other ) noexcept;

(since C++11)

Assigns the contents with those of other. If *this and other both have dynamic type std::bad_alloc then std::strcmp(what(), other.what()) == 0 after assignment. (since C++11)

Parameters

other another exception object to assign with

Return value

*this

std::bad_alloc::what

virtual const char* what() const throw();

(until C++11)

virtual const char* what() const noexcept;

(since C++11)

Returns the explanatory string.

Parameters

(none)

Return value

Pointer to a null-terminated string with explanatory information. The string is suitable for conversion and display as a std::wstring. The pointer is guaranteed to be valid at least until the exception object from which it is obtained is destroyed, or until a non-const member function (e.g. copy assignment operator) on the exception object is called.

Notes

Implementations are allowed but not required to override what().

Inherited from std::exception

Member functions

destroys the exception object
(virtual public member function of std::exception) [edit]
returns an explanatory string
(virtual public member function of std::exception) [edit]

[edit] Example

#include <iostream>
#include <new>
 
int main()
{
    try
    {
        while (true)
        {
            new int[100000000ul];
        }
    }
    catch (const std::bad_alloc& e)
    {
        std::cout << "Allocation failed: " << e.what() << 'n';
    }
}

Possible output:

Allocation failed: std::bad_alloc

[edit] See also

std::bad_alloc means that you have requested more memory than there is available.

You can have situations where a program has no leak, but still genuinely runs out of memory:

vector<long> v;
long n = 0;
for(;;)
{
   v.push_back(n++);
}

will eventually exhaust all available memory in whatever machine you have — but it’s not leaking — all memory is accounted for in the vector. Obviously, ANY container can be made to do the exact same thing, vector, list, map, doesn’t really matter.

Valgrind only finds instances where you «abandon» allocations, not where you are filling the system with currently reachable memory.

What LIKELY is happening is a slower form of the above — you are storing more and more in some container. It may be something you are caching, or something you are not removing when you thought you had removed it.

Watching the amount of memory on the application is actually using in some montioring program («top» in Linux/Unix, «task manager» in Windows) and seeing if it actually grows. If that is the case, then you need to figure out what is growing — for a large program, that can be tricky (and some things perhaps SHOULD grow, others don’t…)

It is of course also possible that you suddenly get some bad calculation, e.g. asking for a negative number of elements in T* p = new T[elements]; would cause bad alloc, since elements is converted to an unsigned, and negative unsigned numbers are HUGE.

If you can catch the bad_alloc in a debugger, that sort of thing is usually pretty easy to spot, because the large amount requested by new will be quite obvious.

Catching the exception in the debugger should in general help, although it is of course possible that you are just allocating memory for a small string when it goes wrong, if you do have something that leaks, it’s not unusual that this is what is allocating when it goes wrong.

If you are using a flavour of Unix, you could also, to speed up the error-finding, set the amount of memory the application is allowed to use to smaller size, using ulimit -m size (in kilobytes) or ulimit -v size.

Why is terminate called after throwing an instance of stdbad alloc is happeningA terminate called after throwing an instance of ‘std::bad_alloc’ is a memory-related error in a programming language C++. What causes the error is a difficult one to track down because it depends on many factors. However, you don’t have any reasons for alarm because we have identified the causes.

Keep on reading, as we’ll teach you what causes this error, and detailed explanations of how to fix them.

Contents

  • Why Is Terminate Called After Throwing an Instance of ‘Std::bad_alloc’ Is Happening?
    • – Memory Allocation Failure
    • – Ram-consuming Tasks in Bedtools
    • – Memory Corruption
  • How To Fix Termination Error?
    • – Use Try-catch Block To Catch the Std::bad_alloc Exception
    • – Use New(Std::Nothrow) To Prevent the Exception
    • – Subset Large Files When Working in Bedtools
    • – Fix Your Code to Avoid the Std::bad_alloc Exception
  • Conclusion

A terminate called after throwing an instance of ‘std::bad_alloc’ failure can occur because the reasons listed below:

  • Memory allocation failure
  • RAM-consuming tasks in Bedtools
  • Memory corruption

– Memory Allocation Failure

In your C++ program, when you allocate large chunks of memory with “new”, an error occurs if you run the program. That’s because such allocation leads to an allocation failure. As a result, the code triggers the ‘std::bad_alloc’ exception. This is C++’s way of telling you to have a second look at your code because there is no memory for such allocation.

For example, in the code below, we allocated a large chunk of memory using the new keyword. We wrote a statement that should print the value of the allocation. However, that won’t happen because you’ll get an error message, and the program aborts.

#include <iostream>
using namespace std;
int main(){
// Try to allocate a very huge amount of memory.
// As a result, memory allocation fails.
int *myarray = new int[10000000000000];
// An attempt to print the error results
// in an exception of std::bad_aloc
cout << myarray;
return 0;
}

– Ram-consuming Tasks in Bedtools

If you are running a RAM-consuming task in a genomics analysis tool like bedtools, you can get an error. This particular error is an indication that the task is taking most of your RAM. Because of this, there is no memory for the task continuation. As a result, you cause the std::bad_aloc exception, leading to the termination of your task.

For example, read the following series of events:

  • You have two files called FileA and FileB
    • FileA is around 18 Megabytes
    • FileB is around Eight Gigabytes
  • You attempted to intersect them with Bedtools
    • You get an error message that a terminate was called after throwing an instance of ‘std::bad_alloc’

These series of events lead to high memory consumption. What’s more, it’s FileB that causes the error due to its large size.

– Memory Corruption

An invalid code can lead to memory corruption, meanwhile, you can be sure that you won’t write invalid C++ code. However, things get funny when your program processes direct input from your user. At a later stage, you use this value with the “new” keyword to allocate memory yet, computation on the input can make the value invalid for the “new” keyword.

But note, computation can lead to memory corruption. That’s because the “new” keyword expects a valid value for memory allocation. So, if the value is not valid, an error occurs down the line. For example, in the next code block, we’ve made the following bad coding decisions:

  • We’ve set up a memory allocation that depends on a direct user input
  • However, we are trusting the user to enter the correct input for the program to run successfully
  • We are using the less than equal operator in a wrong place
  • There is memory leakage because we did not delete memory created with the “new” keyword
  • We’ve used the input operator the wrong way

Due to the decisions listed above, when you run the code, and you enter zero as an input, you’ll get the exception.

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
/**
* This program is faulty in so many ways.
* It’s for demonstration purposes only.
* We have a fixed version later in the article.
*/
char ID[10];
int score[15];
int i;
string user_supplied_ID;
cout<< “Welcome to the program” <<endl;
for (i = 0; i <= 10; i++) {
// Ask the user to enter an ID
cout<< “Please enter an ID:”;
// Read the user input
cin >> user_supplied_ID;
// Try to allocate memory using the user
// supplied ID. Afterward, copy the allocation.
char* temp = new char[user_supplied_ID.size()+1];
user_supplied_ID.copy(temp, user_supplied_ID.size() + 1);
ID[i] = user_supplied_ID[0];
// What’ll happen with these three lines?
temp = new char[user_supplied_ID.size()-2];
user_supplied_ID = user_supplied_ID.substr(2,user_supplied_ID.length());
user_supplied_ID.copy(temp, user_supplied_ID.size() + 1);
score[i] = atoi(temp);
}
cout << endl;
cout << “Name” << ” ” << “Average” << endl;
// Loop through the score array.
// there is an error in the loop. Can you see it?
for (i = 0; i <= 15; i++) {
cout << ID[i] << ” “<< score[i] << endl;
}
return 0;
}

How To Fix Termination Error?

You can fix the termination of your program by taking precautionary actions. Such a precaution includes the use of the try-catch block. The latter applies when using the “new” keyword to allocate memory. What’s more, you can use another variant of the “new” keyword, which is new(std::nothrow).

In addition, when working with large files in bedtools, subset your files into chunks. But don’t forget to write code that prevents memory corruption. Now that you know how to fix the exception, let’s talk about it in detail.

– Use Try-catch Block To Catch the Std::bad_alloc Exception

Since the std::bad_alloc is an exception, you can catch it using the try-catch block. When the exception occurs, you can display a generic error message that has two advantages:

  1. You can write a generic error message in the catch block.
  2. The compiler will not display an exception message.

However, you’ll see the generic message only if you’ve defined it in the catch block. In the following code, we’ve made two modifications to our first example in this article. The modifications are:

  1. We’ve wrapped the memory allocation code in the try block.
  2. We have a defined generic error message in the catch block.

As a result, when you run the code, an exception occurs. However, you’ll see the generic error message and not the exception message.

#include <iostream>
using namespace std;
int main(){
try {
// Try allocating very huge amount of memory
// using the “new” keyword. So, memory allocation fails.
int *myarray = new int[10000000000000];
// If an exception occurs, you’ll not see the
// “success” message below. Meanwhile, the program transfers
// control to the catch block.
cout<<“There was successful memory allocation”<<endl;
}
catch (const bad_alloc& e) { // catch the std::bad_aloc exception
// Tell the user the allocation failed
cout << “Allocation failed: ” << e.what() << ‘n’;
}
return 0;
}

– Use New(Std::Nothrow) To Prevent the Exception

A combination of the “new” and the std::nothrow constant suppresses an exception when it occurs. That’s because the std::nothrow constant tells “new” not to throw an exception on failure, but it should return a null pointer. Therefore, when an exception occurs in your code, you’ll see no exception message.

Using new(std::nothrow) saves us a few lines of code compared to the try-catch block. However, there is no flexibility in writing a generic error message. So, in the code below, we’ve modified the previous code to use std::nothrow. As a result, when you run the code, you’ll see no error message because it’s suppressed.

#include <iostream>
using namespace std;
int main(){
// Try to allocate a very huge amount of memory.
// However, with the std::nothrow constant, you’ll
// see no error message
int *myarray = new(std::nothrow) int[10000000000000];
// Now, when you print the array, you’ll
// get zero and not an exception message.
cout << myarray;
return 0;
}

– Subset Large Files When Working in Bedtools

In Bedtools, when you are working with large files, you should subset them into small chunks. Afterward, you can work on them separately and then merge the files. By doing this, you’ll be able to work with the small chunks, resulting in less RAM consumption. This will help you to avoid the std::bad_aloc exception.

– Fix Your Code to Avoid the Std::bad_alloc Exception

Fixing your code goes a long way in preventing the std::bad_alloc exception. When we say “fixing”, we mean you should write code that’ll not cause memory issues. That’s because if your code causes a memory issue, it increases the chance of an exception. With that said, let’s revisit the code that we showed earlier.

The following is the code from earlier in the article but we’ve added comments that explain the faults in our code.

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
/**
* This program contains talking points
* of our bad coding decisions. Mind you, it still
* contains errors.
*/
char ID[10];
int score[15];
int i;
string user_supplied_ID;
cout<< “Welcome to the program” <<endl;
// OBSERVATION1: In the for loop, we used the
// less than equal (<=) to instead of less than (<) operator.
// As a result, the loop goes out of bounds.
for (i = 0; i <= 10; i++) {
// Ask the user to enter an ID
cout<< “Please enter an ID:”;
// Read the user input
cin >> user_supplied_ID;
// OBSERVATION2: There is no need for the temp string
char* temp = new char[user_supplied_ID.size()+1];
user_supplied_ID.copy(temp, user_supplied_ID.size() + 1);
ID[i] = user_supplied_ID[0];
/**
* OBSERVATION3
* i. If user_supplied_ID.size() is less than 2 char new[] becomes invalid.
ii. If user_supplied_ID.size() is greater than 2 for example 5,
you would allocate tem as only 3 chars without room for the null-terminator.
iii. You would copy 3 chars and the null-terminator into temp. As a result, you can cause memory corruption.
iv. There is memory leakage because we are not deleting
the allocated memory of the “new” operator.
*/
temp = new char[user_supplied_ID.size()-2];
user_supplied_ID = user_supplied_ID.substr(2,user_supplied_ID.length());
user_supplied_ID.copy(temp, user_supplied_ID.size() + 1);
score[i] = atoi(temp);
}
cout << endl;
cout << “Name” << ” ” << “Average” << endl;
// OBSERVATION4: Same as OBSERVATION1
for (i = 0; i <= 15; i++) {
cout << ID[i] << ” “<< score[i] << endl;
}
return 0;
}

Check the following fixed code. In the code, we’ve made significant changes to prevent the std::bad_alloc exception. Our changes include the use of getline() to read the user inputs. In addition, we’ve made adjustments to the for loop and we no longer use std::string.

#include <iostream>
using namespace std;
int main()
{
/**
* This is the fixed version of our program.
* Don’t worry, it does not throw a std::bad_alloc exception!.
* Therefore, run the program, enter zero as an input,
* you’ll get no std::bad_alloc exception.
*/
// Declare the ID and score variables
char ID[15];
int score[15];
cout << “Welcome to the program.nPlease enter 15 different ID numbersn”;
// Contrary to what we did before, we are
// declaring the “i” at the point of usage.
// What’s more, we use the less-than sign
for (int i = 0; i < 15; ++i) {
cout << “Kindly enter an ID:”;
cin >> ID[i];
cin >> score[i];
}
cout << endl;
// Print the IDs and Average values
cout << “Name” << ” ” << “Average” << endl;
// Loop through the score. Also, note that we’ve used
// the less-than sign. This prevents the loop from
// going out of bounds.
for (int i = 0; i < 15; ++i) {
cout << ID[i] << ” ” << score[i] << endl;
}
return 0;
}

Conclusion

This article explained the causes of the std::bad_alloc exception and how you can fix them. So, the following is the summary of our discussion:

  • Large memory allocation with the “new” keyword causes the std::bad_alloc exception.
  • An attempt to intercept a large file in bedtools can cause the std::bad_alloc exception.
  • You can use new(std::nothrow) to prevent the throwing of an exception.
  • Good C++ code can prevent the std::bad_alloc exception.
  • You can catch the std::bad_exception with a try-catch block.

How to fix termination errorThe std::bad_aloc exception can be a tough one to fix. However, everything that you’ve learned in this article will help you prevent and fix it.

  • Author
  • Recent Posts

Position is Everything

Your Go-To Resource for Learn & Build: CSS,JavaScript,HTML,PHP,C++ and MYSQL. Meet The Team

Position is Everything

Цитата
Сообщение от Avazart
Посмотреть сообщение

логичнее убивать сам сценарий

Что значит «сам сценарий»? Сценарий тоже выполняется каким-то кодом. Если сценарий, например, завис, значит и код, который его исполняет тоже завис. Если этот код находится в том же процессе, что и вся остальная машинерия браузера — это проблема.

Цитата
Сообщение от Avazart
Посмотреть сообщение

или поток

Это довольно сложно сделать корректно. В некоторых случаях невозможно. После принудительного завершения потока, в котором исполнялся ошибочный или слишком требовательный к ресурсам код, приводящий к зависанию, в некорректном состоянии может остаться непредсказуемое число ресурсов программы, которые прямо или косвенно с этим потоком разделялись. В этом случае после завершения потока программа будет находиться в состоянии UB. Единственное, что можно сделать с этим — завершить остальной процесс.

Кроме того, как я уже говорил, когда все вкладки браузера находятся в одном адресном пространстве гораздо проще получить несанкционированный доступ к данным. В одном вкладке открыт какой-нибудь онлайн банк, а в соседней сайт злоумышленника, со зловредным скриптом, который ворует данные первой вкладки. Гипотетически сделать это проще, потому что все данные в одном адресном пространстве.

Так что, мультипроцессная организация — это самое логичное, что можно придумать для повышения стабильности работы современного браузера.

Прежде чем возражать мне дальше, советую прочитать также это: https://blog.chromium.org/2008… cture.html

Добавлено через 7 минут

Цитата
Сообщение от Avazart
Посмотреть сообщение

Не давай полномочий и не нужно будет думать о защите.

К сожалению в программах бывают ошибки. Этими ошибками могут воспользоваться злоумышленники.
В современном браузере очень много программного кода, в том числе стороннего — flash контент, java-апплеты, javascript, расширения и т.д. Каждый такой код — потенциальная уязвимость. Лучше и проще сделать архитектуру так, чтобы она сразу отсекала большинство опасных ситуаций.

  • Ошибка status sec img too large
  • Ошибка status sec auth file needed 0xc0030012
  • Ошибка status brom cmd send da fail 0xc0060003
  • Ошибка startuprepairoffline windows 7 что делать
  • Ошибка startuprepairoffline windows 7 решения проблемы