dynamic_bitset, crash my program - c++

I'm new with boost. I have a program which uses dynamic_bitset inside a lambda function. After I try to run the program, I get this message. This message appears even without the function that initializes the bitset and the functions that handle it.
Does anybody know what this message means and what might be the problem?
The message:
/usr/include/boost/dynamic_bitset/dynamic_bitset.hpp:616: boost::dynamic_bitset<Block, Allocator>::~dynamic_bitset() [with Block = long unsigned int, Allocator = std::allocator<long unsigned int>]: Assertion 'm_check_invariants()' failed.
Aborted
well the code is something like this
main call to this function :
int Molecule::initSimilarity(int depth){
cout << "_size is: " << _size << "\t depth is: " << depth << endl; //TODO delete
AtomSet viewing(_size);
int m = 0;
{
// break into initial groups by symbol and valancy
for(int i=0 ; i<_size ; i++)
{
if(viewing[i]) continue;
AtomSet mask = getSetMask( //AtomSet is typedef for dynamic_bitset
[&](const Atom& b)->bool
{
return (!viewing[b._index] && b._valence == _atoms[i]->_valence && strcmp(b._symbol, _atoms[i]->_symbol) == 0);
},
[&](Atom &b)
{
b._class = m; //set the equivalence class of atom 'b' to 'm'
}
);
m++;
viewing |= mask; //viewing now contains a set of atoms and for each atom it's equivalence class
}
cout << "number of equivalence class: " << m << endl; //TODO DELETE!
}
for (int j = 0; j < depth ; j++){
AtomSet viewed(_size);
int before = m;
// iteratively refine the breakdown into groups
for (int i = 0 ; i < _size ; i++) //for any atom A
{
if (viewed[i]) continue;
viewed.flip(i);
AtomSet mask = getSetMask(//put all atoms which are equivalnt but not similar to A in
//their own equivalence class
[&](const Atom& b)->bool
{
if (viewed[b._index])
return false; //if b is in viewed return false;
if (_atoms[i]->_class == b._class) //if in the same class add b to viewed
{
viewed.flip(b._index);
bool similar = !isSimilar(*_atoms[i],b);
return similar;
}
return false;
},
[&m](Atom& b)
{
b._class = m;
}
);
if (!mask.none()) m++;
}
if (before == m){
std::cout << "Finished early after just " << j << " iterations" << std::endl;
return m;
}
}
return m;
}
the signature of getSetMask is:
AtomSet getSetMask(std::function property, std::function action);
and the weirdest thing that even when i remove all the content of that function it still give me the error message

Probably the dynamic_bitset variable that you are referencing in the lambda has gone out of scope and has already been destroyed, or something similar. (Without the source code it's difficult to be more specific)

I had that problem and it took me 3 hours to find out the problem. Here is what can happen: The operator[] in dynamic_bitset does not do bound checking. So, one value can be assigned outside of allowed range and this does not create any error (sanitizer/valgrind do not see anything) since dynamic_bitset is using 64 bit integers (on my computer at least) in order to store values. So, you can get a stored integer of 32 while you allowed only 4 bits in the dynamic_bitset. The error is triggered at a later time when m_check_invariant() is called for example when the destructor is called.
So, the problem becomes to find this range error. The solution is to edit the boost/dynamic_bitset.hpp and add print statement in the code of operator[] when an operation out of range is called. If you cannot do that then download the boost library and install it in your home directory.

I had a similar problem with dynamic_bitset that was solved by calling reset() on it before it got destroyed.

That can indicate that you are writing past the end of the bitset without resizing it. Might want to do some bounds checking.

Read the explaination of Mathieu Dutour Sikiric. The problem is that you write outside of allowed range of the bitset via operator[] and this does not create any error because it's boost and it doesn't bother to waste compute time checking that you have right to write where you want. It is C++ you know...
So to detect it, go to boost/dynamic_bitset/dynamic_bitset.hpp, and modify the code to impose checks every time you use operator[].
boost/dynamic_bitset/dynamic_bitset.hpp, around line 300.
reference operator[](size_type pos) {
assert(m_check_invariants());
return reference(m_bits[block_index(pos)], bit_index(pos));
}
bool operator[](size_type pos) const {
assert(m_check_invariants());
return test(pos);
}
This makes it easier to detect the error in your code.

Related

How can I fix an assertion failure that states 'vector subscript out of range' [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Other questions that I viewed before posting this question:
Debug Assertion Failed: Vector subscript out of range
Debug Assertion Failed Vector Subscript Out of Range C++
I am working on a Boids project, details of which can be found here:
https://www.red3d.com/cwr/boids/
From what I can gather my issue is something to do with an index getting accessed by the function but no data is present in the index. I had this issue yesterday in a different area of my code and fixed it by making one of my getters return a reference rather than a copy of a class object. That approach seems to not be the issue today.
Below is my code:
This code is a snippet from my function that handles simulation events. This is the code that I have narrowed down the issue to.
//Remove flocking organisms with < 0 enery storage.
for (int i = 0; i < m_flock.getSize(); i++)
{
if (m_flock.getOrganism(i).getEnergyStore() <= 0)
{
m_flock.removeOrganism(i);
//m_notFlocking.flock.erase(m_notFlocking.flock.begin() + i);
cout << "Organism died and has been removed..." << endl;
}
}
The code below is from my Flock.cpp class definition file which details information on storing boids in a vector to then apply flocking behaviors to. This class function is giving the following error:
Unhandled exception at 0x7B87FC66 (ucrtbased.dll) in EvoSim.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
Code:
Organism &Flock::getOrganism(int i)
{
return flock[i];
}
My suspicion is that the for loop size is not reflecting the recently erased object.
How can I fix the vector subscript error?
Edit:
This is the break point that shows up in the debugger:
_NODISCARD _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ {
auto& _My_data = _Mypair._Myval2;
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(
_Pos < static_cast<size_type>(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _My_data._Myfirst[_Pos];
}
Edit 2:
I did some messing around and discovered the issue only occurs when I run VS 2019 in debug mode, otherwise in Release mode it works fine and as expected.
I see nothing in this code that can cause an out of bounds access. However, you should not increment i on any loop iteration that removes an organism, otherwise you will skip the next organism in the list.
Imagine on the 1st loop iteration, the organism at index 0 needs to be removed. Subsequent organisms move down the list. On the next loop iteration, i gets incremented to 1, and the organism that had moved into index 0 is skipped.
Try this instead:
//Remove flocking organisms with < 0 enery storage.
for (int i = 0; i < m_flock.getSize(); )
{
if (m_flock.getOrganism(i).getEnergyStore() <= 0)
{
m_flock.removeOrganism(i);
cout << "Organism died and has been removed..." << endl;
}
else
++i;
}
Alternatively, you can replace the entire loop using the erase-remove idiom via std::remove_if() and std::vector::erase(), eg:
void Flock::removeDeadOrganisms()
{
//Remove flocking organisms with < 0 enery storage.
flock.erase(
std::remove_if(flock.begin(), flock.end(),
[](const auto &o){ return o.getEnergyStore() <= 0; }
),
flock.end()
);
}
...
m_flock.removeDeadOrganisms();
Or, in C++20, via std::erase_if(), eg:
void Flock::removeDeadOrganisms()
{
//Remove flocking organisms with < 0 enery storage.
std::erase_if(flock,
[](const auto &o){ return o.getEnergyStore() <= 0; }
);
}
To loop though a vector that you are also modifying you don't want to i++ on every loop, since if the element was removed you don't need to increment the index. There are two solutions to this, either you can conditionally increment the index at the end of the loop or you can loop though the list backwards.
int i = 0;
while (i < m_flock.getSize())
{
if (m_flock.getOrganism(i).getEnergyStore() <= 0)
{
m_flock.removeOrganism(i);
cout << "Organism died and has been removed..." << endl;
}
else
{
i++;
}
}
for (int i = m_flock.getSize(); i ; i--)
{
if (m_flock.getOrganism(i).getEnergyStore() <= 0)
{
m_flock.removeOrganism(i);
cout << "Organism died and has been removed..." << endl;
}
}
You can't use a normal iterator loop for this because vector::erase "Invalidates iterators and references at or after the point of the erase, including the end() iterator". However, you can use std::remove_if.
m_flock.erase(std::remove_if(m_flock.begin(),
m_flock.end(),
[](Organism org){
return org.getEnergyStore()<=0;
}));

C++ There is a bool return type function returning (24) here

First of all sorry for too much code
Here there is a vector (teamNum) with type class, the class contain a vector (player) with type struct, it is a little complicated, but here in this function I need to check if there is a player in teamNum which contain tName equal to _tname (function parameter) contain (the player) pID equal to _pID (function parameter)
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
if (teamNum[i].tName == _tname)
{
for (int j = 0; j < teamNum[i].player.size(); j++)
{
if (teamNum[i].player[j].pID == _pID)
return true;
}
}
else if (i == (teamNum.size() - 1))
{
return false;
}
}
}
And in the main
int main()
{
cout << "\n" << thereIsSimilarID("Leverpool", 1) << endl;
}
The output is 24 !!!!!
(good note that this happen just when the team (Leverpool) is the last team in the vector teamNum)
Again sorry for too much code but I need to know the bug not only fix the problem I need to learn from you
You encountered undefined behaviour.
If you take the if (teamNum[i].tName == _tname)-branch on the last element, but find no player with the correct pID, you don't return anything. Which means, that the return value is whatever random value is currently in the memory location that should hold the return value. In your case it happens to 24. But theoretically, everything could happen.
The same problem occurs when teamNum is empty.
The solution is to make sure to always return a value from a function (except if it has return type void of course):
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
// In this loop return true if you find a matching element
}
// If no matching element was found we reach this point and make sure to return a value
return false;
}
You should take a look at your compiler settings and enable all the warnings. And often it's good to let it treat certain warnings as errors.

Try to use llvm LoopPass to find number of loops in program

I am trying to write a llvm pass program to count the number of loops within a program. Then I find LoopPass, which is explained in following link:
http://llvm.org/docs/WritingAnLLVMPass.html#the-looppass-class
Three functions are mentioned: doInitialization, runOnLoop, doFinalization.
I originally consider that "doInitialization" runs once at the start of program, "runOnLoop" runs for each time a loop is finished, and "doFinalization" runs at the end of program. I want to define a variable as counter, to be set to "0" in "doInitialization", count++ in "runOnLoop", and output result in "doFinalization".
Here is my code (partial):
virtual bool doInitialization(Loop * L, LPPassManager &LPM)
{
errs() << (*(L->block_begin()))->getParent()->getName() << '\n';
count = 0;
length = 0;
return false;
}
virtual bool runOnLoop(Loop * L, LPPassManager &LPM){
count++;
for(Loop::block_iterator b = L->block_begin(), e = L->block_end(); b != e; b++)
{
length++;
}
return false;
}
virtual bool doFinalization()
{
errs() << "# of loops: " << count << '\n';
errs() << "average depth of loop: " << (float)(length)/count << '\n';
return false;
}
But from the result, "doInitialization" seems to work for number of times equal to number of loops in one function, "runOnLoop" works as expected, "doFinalization" seems to work at the end of a function. So I get two problems:
Why should "doInitialization" works multiple times?
If I want to get the total number of loops within a program (a program may have many functions, I do want "doFinalization" works only once for a program), what should I do?
Thanks to all relative answers,
Why is doInitialization called multiple times?
Counting all loops within the program I would write a ModulePass and overwrite its runOnModule(). Module M you can access all functions (I think the begin and end function should return appropriate iterators).
Then I can use getAnalysis() to get a LoopInfo object for the specified function. That object provides iterators to iterate over all top-level loops. If such a loop contains nested loops all nested loops of the "second level" can be retrieved by using getSubLoops. So for nested loops you would have to use that getSubLoops recursivly until no more subloops exist. Then I could increase some counter for each loop object. So it would look like this (I know that code is not compiling):
int loopcounter;
void handleLoop(Loop *L) {
++loopcounter;
for (Loop *SL : L->getSubLoops()) {
handleLoop(SL);
}
}
virtual bool runOnModule(Module&M) {
loopcounter = 0;
for (auto &IT = M.begin, END = M.end(); IT != END; ++IT) {
LoopInfo &LI = getAnalysis<LoopInfo>(*IT);
for (LoopInfo::iterator LIT = LI.begin(), LEND = LI.end(); LIT != LEND; ++LIT) {
handleLoop(*LIT);
}
}
DEBUG(errs() << "Found " << loopcounter << " loops.\n");
}
To make the getAnalysis call work properly you will have to overwrite the getAnalysisUsage() and add a dependency to LoopInfo by calling AU.addRequired<LoopInfo>().
Because the loop pass is not initialized once for an entire compilation, it's initialized everytime you analyze a loop.
I'd add a debug statement to an existing loop pass that prints something unique, then use grep -c on the output of a compliation with -debug-only=<pass_you_modified>

Searching a vector of object pointers

I have a Player class where each object of the type Class has a name, wins, losses, and draws. Each object of the Player class is created by calling the_player = new Player(the_name). When the user inputs a new name to add a Player object to the program a pointer is pushed into a vector AllPlayers. The program should check before pushing the new pointer that the desired player does not already exist in said vector. I have to do this check several times throughout my program so I thought I'd write a function for it. Here is my function:
int findPlayer(vector<Player*> &vals, string name_in)
{
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
else
return -1;
}
};
When the option is requested to add a new Player the following code is used:
do {
cout << "Name: ";
cin >> the_name;
if (findPlayer(AllPlayers, the_name) != -1){
cerr << "Player already exists\n";
}
} while (findPlayer(AllPlayers, the_name) != -1);
the_player = new Player(the_name);
AllPlayers.push_back(the_player);
For some reason, though, every time I try to add a new player it throws "Player already exists" and never leaves the do-while loop. This is even true when the AllPlayers vector is empty. I added a cout << findPlayer(AllPlayers, the_name) for debugging and it printed 4192252 which I assume is the largest element possible in a vector.
So the question is: Why does it return 4192252 rather than -1?
If vals is empty then the for loop is never entered and the function exits without hitting a return statement. Meaning that you get a random value returned instead, in this case 4192252 happens to be in the return register. Your compiler warnings will have told you this if you read them.
What you think, what will be returned from findPlayer if vals is empty?
Is it defined?
If the vector is empty, you don't enter the loop at all, so don't reach a return statement and don't return a valid value. You should enable compiler warnings to catch this error.
Otherwise, you only check the first item, and return immediately whether or not it matched. You want to return if you find a match, but keep looking otherwise, and only return -1 if there is no match:
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
The find player function should be something like:
int findPlayer(vector<Player*> &vals, string name_in)
{
if(vals.size() == 0)
return -1;
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
};
Rewrite the function the following way
bool findPlayer( const std::vector<Player*> &vals, const std::string &name_in )
{
std::vector<Player*>::size_tyoe i = 0;
while ( i < vals.size() && vals[i]->getName() != name_in ) ++i;
return i != vals.size();
}
Take into account that member function getName has to be defined with qualifier const.
As for your function then it returns nothing in case when the vector is empty or returns -1 in case when the first element of the vector does not coincide with the string.
Take into account that there is standard algorithm std::find_if declared in header <algorithm> that can be used instead of your function.

Is it possible see the value returned in c++?

So..I'm testing a function with assert: (The value of pBola1 is 1)
assert(BomboTest.TreureBola(1)==pBola1);
BomboTest.TreureBola it's a function that returns a random number (in this case has to return 1) of a list.
cBola* cBombo::TreureBola(int num)
{
int posicio_aleatoria;
posicio_aleatoria= rand() % (num);
return(Boles.TreureElement(posicio_aleatoria));
}
And TreureElement it's a function that returns an element of a dynamic list knowing the position of the element that you want to extract(in this case returns 'retorn' which is 1)
cBola* cLlista::TreureElement(int posicio)
{
int i;
cBola* recorreLlista;
cBola *retorn;
recorreLlista=primer;
retorn = primer;
i=0;
if (posicio == 0)
{
primer = (*primer).getSeguent();
}
else
{
// Busquem la posiciĆ³ //
while(i < posicio)
{
recorreLlista= retorn;
retorn = (*retorn).getSeguent();
i++;
}
(*recorreLlista).setSeguent( (*retorn).getSeguent() );
}
numElements--;
return retorn;
}
And I don't know why but the assert fails. I can see the value returned by TreureElement because I have the pointer 'retorn' but I can't know the value returned by TreureBola..There is some way to see that value returned by TreureBola in the debugger?
PD:I'm using visual studio 2010
Just create a local
cBola* pTemp = BomboTest.TreureBola(1);
assert(pTemp==pBola1);
You could look in the dissasembly and inspect the return registry, but this seems like overkill. The above is the correct approach and others will thank you in the future, when they encounter the same problem.
You can always temporarily change
assert(BomboTest.TreureBola(1)==pBola1);
to`
auto tmp=BomboTest.TreureBola(1);
assert(tmp==pBola1);
and place a breakpoint on the first line.
I would write a small wrapper around assert to use instead:
template <typename T>
void compare(const T& lhs, const T& rhs)
{
if (lhs != rhs)
cout << "The values were not the same! " << lhs << " vs. " << rhs << endl;
assert(lhs == rhs);
}
This will still call assert, but first you'll get some (hopefully) useful output first.
So instead of calling:
assert(BomboTest.TreureBola(1)==pBola1);
You would call:
compare(BomboTest.TreureBola(1), pBola1);
This has an added benefit that you can place a breakpoint here and see see what TreureBola returned in the debugger, too.