C ++ memory allocation errors without using new

I am having problems with the fact that my program throws a large number of memory allocation exceptions, and it is very difficult for me to diagnose the problem ... I would publish the code, but my program is very large, and I have my own problems with the information, so I hope to get help without publishing code. If you plan to respond in any way to SSCCE comments, just stop reading now and save us both for a while. This is the case when I cannot publish a short code - I will try to be as clear and concise as possible with a description of the problem and some specific questions.

The program background - my program - is basically a data cruncher. He takes a bunch of data tables as inputs, performs calculations on them and spills out new data tables based on the calculation results. All my data structures are user classes (consisting of int, double, and string types with vector containers for arrays). In all cases, I run instances of class variables without using new and deleted ones.

Problem Description - My program compiles without warning and works great with smaller datasets. However, as soon as I increase the data set (from an array of 20x80 to 400x80), I start throwing bad_alloc exceptions (as soon as I have processed the first 35 records or so). Large datasets work fine in 17 of my 18 modules - I highlighted one function where errors occur. The calculations necessary for this function will lead to the creation of about 30,000 rows of data, while other functions in my code generate 800,000 rows without incident.
The only real unique attribute in this module is that I resize a lot (about 100 times per function call), and that the function uses recursive loops during the resize operation (the function allocates square feet from the building, one of the tenants for a while, and then updating the remaining legs, which will be allocated after the tenant's lease size and duration are allocated until all square feet are allocated). In addition, the error occurs in almost the same place every time (but not in the same place, because I have a random number generator that throws some changes to the results). What really scares me is that the first 34 calls to this function work fine, and the 35 call does not require more memory than the previous 34, but I have these bad_alloc exceptions on the 35th call, though ...

It's hard for me to cope without code. Please just try to give me some direction. My specific questions are as follows:

  • If I do not use "new" and "delete" and all my variables are initialized with INSIDE for local functions, is it possible to have problems with memory leak / allocation when re-calling functions? Is there anything that I can or should do to manage memory when variable initialization enables a local function using "vector Instance"; declare variables?

  • Is it likely that I am on a low stack memory if I am doing the whole program through the stack? Is it possible for me to load some of my large search tables (maps, etc.) into a bunch, and then just use the stack for my iterations, where speed matters?

  • Is there a memory resizing issue? Could this be an instance where I have to use “new” and “delete” (in many cases I was not recommended to use them unless there is a very strong specific reason for this)?

  • [Related to 3] Inside the problem function, I create a class variable and then write this variable about 20 times (once for each "iteration" of my model). I don’t need the data from the previous iteration when I do this ... so I could supposedly create a new instance of the variable for each iteration, but I don’t understand how this will be useful (since I can clearly do all 20 iterations in one instance on the first ~ 34 data slices)

Any thoughts would be appreciated. I can try to post some code, but I already tried this, and everyone seemed to be distracted by the fact that it was not compiled. I can publish this function, but it does not compile on its own.

Here is the class that causes the problem:

// Class definition class SpaceBlockRentRoll { public: double RBA; string Tenant; int TenantNumber; double DefaultTenantPD; int StartMonth; int EndMonth; int RentPSF; vector<double> OccupancyVector; vector<double> RentVector; }; // Class variable declaration (occuring inside function) vector<SpaceBlockRentRoll> RentRoll; 

In addition, here is a snippet from the function in which the recursion occurs

 for (int s=1; s<=NumofPaths; ++s) { TenantCounter = 0; RemainingTenantSF = t1SF; if (RemainingTenantSF > 0) { while (RemainingTenantSF > 0) { TenantCounter = TenantCounter + 1; // Resize relevant RentRoll vectors ResizeRentRoll(TenantCounter, NumofPaths, NumofPeriods, RentRoll); // Assign values for current tenant RentRoll[TenantCounter] = AssignRentRollValues(MP, RR) // Update the square feet yet to be allocated RemainingTenantSF = RemainingTenantSF - RentRoll[TenantCounter].RBA; } } } 
+4
source share
4 answers

bad_alloc occurs due to heap problems and can be thrown by any code that indirectly allocates or frees heap memory, which includes all standard library collections ( std::vector , std::map , etc.), as well std::string .

If your programs don’t use a lot of heap memory (therefore they don’t have enough heap), bad_alloc is most likely caused by damage to the heap, which is usually caused by using dangling pointers to the heap.

You note that your code performs many resize - resize operations in most collections, it will invalidate all iterators in the collection, so if you reuse any iterator after resize , it can damage the heap, bad_alloc exception. If you use uncontrolled access to vector elements ( std::vector::operator[] ), and your indexes are out of range, this can also damage the heap.

The best way to track heap errors and memory errors in general is to use a heap debugger like valgrind

+6
source

Classes like std::vector and std::string allowed to throw bad_alloc or other exceptions. In the end, they have to use some memory that comes from somewhere, and on any computer there is so much memory to get around.

Standard 17.6.5.12/4:

Destructor operations defined in the C ++ standard library should not exclude exceptions. Each destructor in the C ++ standard library should behave as if it had an exception specification to exclude metadata. Any other functions defined in the C ++ standard library that do not have an exception specification may throw exceptions for implementation, unless otherwise specified. [Footnote 1] An implementation can strengthen this implicit exception specification by adding an explicit one.

Footnote 1: In particular, they may report an inability to allocate storage by throwing an exception of type bad_alloc or a class derived from bad_alloc (18.6.2.1). Library implementations should report errors by throwing exceptions or derivatives of standard exception classes (18.6.2.1, 18.8, 19.2).

+3
source

If I do not use "new" and "delete" and all my variables are initialized with INSIDE for local functions, is it possible to have problems with memory leak / allocation problems when calling functions again?

unclear. If all the variables you are referencing are local, no. If you use malloc (), calloc () and free (), yes.

Is it likely that I am on a low stack memory if I am doing the whole program through the stack?

Not if you get bad_alloc. If you get a "stack overflow" error, yes.

Is it possible for me to load some of my large search tables (maps, etc.) into a bunch, and then just use the stack for my iterations, where speed matters?

Well, it's hard to believe that you need a local copy of the lookup table in every frame of the recursive method stack.

Is there a memory resizing issue?

Sure. You can end.

Could this be an instance where I have to use "new" and "delete"

Impossible today without knowing more about your data structures.

(In many cases, I was not recommended to use them if there is no very strong specific reason for this)?

By whom? Why?

Inside the problem function, I create a class variable,

An instance of the class is created on the stack. I think. Please clarify.

then writing this variable about 20 times (once for each iteration of my model).

With an appointment? Does the class have an assignment operator? Is it correct? Does the class itself use heap memory? Is it properly distributed and removed during construction, destruction and assignment?

+2
source

Since, as you said, you are using std::vector with the default allocator, the problem occurs when you use a lot of std::vector::resize(...) , and this happens after some iterations, I assume that you ran into with heap fragmentation problem.

+2
source

Source: https://habr.com/ru/post/1494382/


All Articles