vector.push_back() crashes - c++

I have a problem while working with vectors of a class. I have tried whittling away at the code as much as possible, leaving me with the code below. Yet, after doing this, I still cannot figure out why my program is crashing. I come from a world of VBA and my C++ debugging skills are poor to say the least and I apologize for that up front. Any guidance to improve my ability here will be gladly accepted.
My class:
class Tester {
public:
int varA;
int varB;
Tester() {
varA = 1;
varB = 1;
}
Tester(Tester& P1, Tester& P2) {
varA = P1.varA + P2.varA;
varB = P1.varB + P2.varB;
}
Tester(const Tester &Source) {
varA = Source.varA;
varB = Source.varB;
}
};
My test mains:
Does not work:
int main() {
std::vector < Tester > BreakIt;
for (int i = 0; i < 2500; i++) {
Tester newTester;
BreakIt.push_back(newTester);
Tester& tempTester = BreakIt.at(0);
for (int j = 0; j < 4; j++) {
BreakIt.push_back(Tester(newTester, tempTester)); //This is where it crashes.
}
}
return 0;
}
Does work:
int main() {
std::vector < Tester > BreakIt;
Tester newTester;
BreakIt.push_back(newTester);
for (int i = 0; i < 2500; i++) {
Tester& tempTester = BreakIt.at(0);
for (int j = 0; j < 4; j++) {
BreakIt.push_back(Tester(newTester, tempTester));
}
}
return 0;
}
Does work:
int main() {
std::vector < Tester > BreakIt;
for (int i = 0; i < 2500; i++) {
Tester newTester;
BreakIt.push_back(newTester);
Tester& tempTester = BreakIt.at(0);
}
return 0;
}
The push_back() line that breaks does run a few times before the crash. It seems that when I change certain things around and recompile, the point at which it crashes changes (i.e. 20 times through the main loop vs. 175 times vs. 1000 times). However, once I've compiled, it will typically run through the the same iteration each time before crashing.
I suspect that this is some kind of 'undefined behavior' but from where I'm not sure.
Can someone please help me identify why BreakIt.push_back(Tester(newTester, tempTester)); does not work where I want it to?

You're right, there is undefined behaviour.
You're taking a reference to BreakIt.at(0); however this object is no longer guaranteed to exist after you've done a push_back, because if the vector grows, all of the contents are typically copied, and the originals deleted.
From http://www.cplusplus.com/reference/stl/vector/push_back/ (not the world's best reference):
Reallocations invalidate all previously obtained iterators, references and pointers.

For me, it was the issue with the MinGW version (MinGW g++ 6.3.0) which I updated to 7.2.0 from https://mingw-w64.org/doku.php/download.
Now it's working fine.

Related

Fast construction of unordered_map with nested vector with preallocation std::unordered_map<int, vector<Thing *>>?

I want to create map of int to vector of Things*. I know that Thing will be 1-50 no more. How can I allocate 50 at start to speed up construction of map?
I tried three methods but still not sure if it enough fast. Can you suggest better optimization?
I was using c++ 10 years ago and I am not sure if I do it correctly. Can you help?
All optimization suggestions are welcome. Code is simplified from real problem.
#include <iostream>
#include <vector>
#include <unordered_map>
#include <time.h>
class Thing {
};
int main()
{
clock_t start;
start = clock();
auto int_to_thing = std::unordered_map<int, std::vector<Thing *>>();
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 25; j++) {
int_to_thing[i].push_back(new Thing());
}
}
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 25; j++) {
int_to_thing[i].push_back(new Thing());
}
}
std::cout << (clock() - start) << std::endl;
start = clock();
int_to_thing = std::unordered_map<int, std::vector<Thing *>>();
for (int i = 0; i < 1000; i++) {
int_to_thing[i].reserve(50);
for (int j = 0; j < 25; j++) {
int_to_thing[i].push_back(new Thing());
}
}
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 25; j++) {
int_to_thing[i].push_back(new Thing());
}
}
std::cout << (clock() - start) << std::endl;
start = clock();
int_to_thing = std::unordered_map<int, std::vector<Thing *>>();
for (int i = 0; i < 1000; i++) {
auto it = int_to_thing.find(i);
if (it != int_to_thing.end()) {
auto v = std::vector<Thing *>(50);
auto pair = std::pair<int, std::vector<Thing *>>(i, v);
int_to_thing.insert(pair);
}
}
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 25; j++) {
int_to_thing[i].push_back(new Thing());
}
}
std::cout << (clock() - start) << std::endl;
return 0;
}
Are you concerned about the construction of the map (then see #ShadowRanger's comment) or the construction of the vectors?
I assume that there are 1..50 Thing's in a vector, NOT 1..50 vectors in a map.
Your code:
int_to_thing = std::unordered_map<int, std::vector<Thing *>>();
for (int i = 0; i < 1000; i++) {
int_to_thing[i].reserve(50);
is the best option. It constructs a map of vectors and, inside the loop, creates each vector and pre-allocates room for 50 elements.
Without that reserve() you would likely encounter a couple of reallocation while pushing 50 elements into those vectors.
Using:
auto v = std::vector<Thing *>(50);
actually creates 50 elements in your vector,and default-initializes them. This may or may not cost you extra. Specifically, it will be cheap with your current use of pointers, and expensive if you switch to storing the Thing objects themselves.
If you are unsure that something is fast enough then you are not measuring performance and this is prima facie evidence that you don’t care one iota about it. If you don’t measure it then you cannot claim anything about it. Measure it first before you do anything else. Otherwise you’ll waste everyone’s time. You work on an assumption that such preallocations will help. I have an inkling that they won’t help at all since you make so few of them, and you’re just wasting your time. Again: if you are serious about performance, you stop now, get measurements in place, and come back with some numbers to talk over. And don’t measure debug builds - only release builds with full optimization turned on, including link time code generation (LTCG). If you don’t optimize, you don’t care about performance either. Period. Full stop. Those are the rules.
Yes, you have code that times stuff but that’s not what measurements are about. They need to happen in the context of your use of the data, so that you can see what relative overhead you have. If the task takes an hour and you spend a second doing this “unoptimally”, then there’s no point in optimizing that first - you got bigger fish to fry first. And besides, in most context the code is cache-driven ie data access patterns determine performance so I don’t believe you’re doing anything useful at all at the moment. Such micro optimizations are totally pointless. This code doesn’t exist in a vacuum. If it did, you can just remove it and forget about it all, right?

c++ int in class gets set to value, seemingly out of nowhere

The int winner should be set to 2 under certain conditions but it's somehow being set to a variety of higher values, most commonly 6. I have no idea how this is happening, as there is no other function in my class that affects winner, and the variable isn't even mentioned anywhere else in the program. What is most confusing to me is that I have an almost identical function (P2Move()) that is literally identical in how it sets the winner variable to P1Move(), and that function runs perfectly.
Some info: The class this is part of is called Board, which acts as a checkerboard array made up of Square class objects.
Below is the function causing the problem. Near the bottom, the statement else if((canTake.size()==0)&&(canMove.size()==0)) {Board::winner = 2;} causes the problem. Everything else seems to work when I remove the problematic part from the function, but I need that part to work in order to submit the final project.
void Board::P1Move()
{
P1pieces = 0;
std::vector <Move> canMove;
std::vector <Move> canTake;
for(int j = 0; j < bSize; j++)
{ //Start of j loop.
for(int i = 0; i < bSize; i++)
{ //Start of i loop.
Square sq = board[i][j];
bool cTakeL = canTakeL(i,j);
bool cTakeR = canTakeR(i,j);
bool cMoveL = canMoveL(i,j);
bool cMoveR = canMoveR(i,j);
if(board[i][j].getPl() == P1)
{
P1pieces++;
if(cTakeL)
{
Move a = Move(sq.getIndex(),board[i-2][j+2].getIndex(),board[i-1][j+1].getIndex(),0);
canTake.push_back(a);
}
if(cTakeR)
{
Move b = Move(sq.getIndex(),board[i+2][j+2].getIndex(),board[i+1][j+1].getIndex(),0);
canTake.push_back(b);
}
if(cMoveL)
{
Move c = Move(sq.getIndex(),board[i-1][j+1].getIndex(),0,0);
canMove.push_back(c);
}
if(cMoveR)
{
Move d = Move(sq.getIndex(),board[i+1][j+1].getIndex(),0,0);
setWinner(d.getSpos());
canMove.push_back(d);
}
}
} //End of i loop.
} //End of j loop.
if(canTake.size()!=0)
{
time_t t;
time(&t);
srand(t);
int moveNum = rand()%canTake.size();
std::string output = "p1 ";
Move out = canTake.at(moveNum);
int i = 0;
int j = 0;
for(int y = 0; y < bSize; y++)
{
for(int x = 0; x < bSize; x++)
{
if(board[x][y].getIndex()==out.getSpos())
{
i = x;
j = y;
}
}
}
if(board[i-2][j+2].getIndex()==out.getEndPos())
{
board[i-2][j+2].setOcc(true);
board[i-2][j+2].setPl(P1);
board[i-1][j+1].setOcc(false);
board[i-1][j+1].setPl(NA);
}
else if(board[i+2][j+2].getIndex()==out.getEndPos())
{
board[i+2][j+2].setOcc(true);
board[i+2][j+2].setPl(P1);
board[i+1][j+1].setOcc(false);
board[i+1][j+1].setPl(NA);
}
output = output + out.toString();
setCmove(output);
board[i][j].setOcc(false);
board[i][j].setPl(NA);
}
else if(canMove.size()!=0)
{
time_t t;
time(&t);
srand(t);
int moveNum = rand()%canMove.size();
std::string output = "p1 ";
Move out = canMove.at(moveNum);
int i = 0;
int j = 0;
for(int y = 0; y < bSize; y++)
{
for(int x = 0; x < bSize; x++)
{
if(board[x][y].getIndex()==out.getSpos())
{
i = x;
j = y;
}
}
}
if(board[i-1][j+1].getIndex()==out.getEndPos())
{
board[i-1][j+1].setOcc(true);
board[i-1][j+1].setPl(P1);
}
else if(board[i+1][j+1].getIndex()==out.getEndPos())
{
board[i+1][j+1].setOcc(true);
board[i+1][j+1].setPl(P1);
}
output = output + out.toString();
setCmove(output);
board[i][j].setOcc(false);
board[i][j].setPl(NA);
}
else if((canTake.size()==0)&&(canMove.size()==0))
{
Board::winner = 2;
}
P1pieces = canTake.size() + canMove.size();
}
You are working with std::vector, which is a good thing. (Too much beginner "C++" code uses C arrays.) The vector class template allows for a pretty easy way to find out if and where you might have an out-of-bounds access (as suggested in the comments):
Instead of accessing vector elements using operator[], change your code to use the .at() member function. .at() is bounds-checking, and will throw an exception if you access out-of-bounds (instead of silently breaking your program).
In production code, operator[] is usually preferred as omitting the bounds check is more efficient. But while learning, .at() can help you quite a bit.
Also, getting in the habit of using code checkers like valgrind or the assert macro to check your assumptions is a good thing, even when you got past the point where you wouldn't use .at() anymore.

C++ code crashing when using function instead of inline code

C++ rookie here.
I have the following code:
std::vector<float> MyBuffer::readAverage(int numberOfBuffers) {
std::vector<float> result = std::vector<float>(streams.size());
for (int i = 0; i < streams.size(); ++i) {
result[i] = getAverage(streams[i], numberOfBuffers);
}
return result;
}
float MyBuffer::getAverage(std::deque<float> input, int numberOfBuffers) {
float sum = 0;
for (int i = 0; i < numberOfBuffers; ++i) {
sum += input[i];
}
return sum / numberOfBuffers;
}
This code randomly crashes at getAverage(), I am not sure why.
Strange thing (for me as a C++ rookie at least) is that when I inline the function, it does not crash:
std::vector<float> MyBuffer::readAverage(int numberOfBuffers) {
std::vector<float> result = std::vector<float>(streams.size());
for (int i = 0; i < streams.size(); ++i) {
float sum = 0;
for (int i1 = 0; i1 < numberOfBuffers; ++i1) {
sum += streams[i][i1];
}
result[i] = sum / numberOfBuffers;
}
return result;
}
I can understand that there may be many reasons why this specific code is crashing - so my question relates more to what changes when I inline it, rather than calling a function? In my mind it should be exactly the same thing, but I guess there is something about the way C++ works that I am not grasping?
The program has many potential reasons why it can cause a crash.
bufferDurationMs is not initialized in the provided code, I hope its initialized to value other than 0.
for (int i = 0; i < streams.size(); ++i) {
result[i] = getAverage(streams[i], numberOfBuffers); } use result.size() instead of streams.size() as result is lvalue. It
is better to check both of these conditions in for.
It is quite possible that numberOfBuffers can be 0 in which case code would crash(divide by zero)
Some optimizations that can be done in the code:
std::vector<float> result = std::vector<float>(streams.size()); use reserve rather than using a costly operation of creating a
vector and assigning it to lvalue.
std::vector result; result.reserve(streams.size());
float MyBuffer::getAverage(std::deque<float> input, int numberOfBuffers) prefer const reference rather than creating a copy
of an object
const std::deque& input

cout statement change program semantics

I have the following piece of code, which is part of a class, whose details hopefully are not important for answering that question. I don't want an exact solution to my problem, but only an explanation, how the behavior, I'm going to describe, can occur.
Character operator+(Character c) {
std::vector<float> resDensity(density);
float l;
float dh;
for (int i = 0; i < domains.size(); i++) {
for (int j = 0; j < c.domains.size(); j++) {
l = (domains[i].intersection(c.domains[j])).length();
//std::cout << l;
dh = c.density[j] * l / domains[i].length();
resDensity[i] += dh;
}
}
std::vector<Domain> h(domains);
return Character(h, resDensity);
}
You probably noticed the commented cout statement. Due to a numeric bug in my program, I followed the falsy value until I detected the variable l. So I printed it to the console and found out, that the value is exactly the value I need, and also the program works just fine and the bug simply vanished. Uncommenting it, again, leads to the undesired misbehavior.
The Character class contains the fields domains and density, both vectors...
The length and intersection method:
float length() {
float res;
for (int i = 0; i < is.size(); i++) {
res += is[i].b - is[i].a;
}
return res;
}
Domain intersection(Domain d) {
std::vector<Interval> hi;
for (auto i = is.begin(); i != is.end(); i++) {
for (auto j = d.is.begin(); j != d.is.end(); j++) {
hi.push_back(i->intersection(*j));
}
}
Domain hhh(hi);
return hhh;
}
I compiled the code with g++ --std=c++11 ...
g++ --version
g++ (GCC) 4.8.2 20131219 (prerelease)
In your length() function the res variable is uninitialized:
float res;
for (int i = 0; i < is.size(); i++) {
res += is[i].b - is[i].a; // <-- uses an uninitialized res
}
How is length() calculated on Domain? hhh is a local variable that you are returning, so a copy will be made. If length() depends on something that is not copied then you will see strange behaviour. What if you just change intersection() to return a float or create a different method called intersectionLength() which returns a float - do you still get the heisenbug?

c++ counting sort

I tried to write a countingsort, but there's some problem with it.
here's the code:
int *countSort(int* start, int* end, int maxvalue)
{
int *B = new int[(int)(end-start)];
int *C = new int[maxvalue];
for (int i = 0; i < maxvalue; i++)
{
*(C+i) = 0;
}
for (int *i = start; i < end; i++)
{
*(C+*i) += 1;
}
for (int i = 1; i < maxvalue-1 ; i++)
{
*(C+i) += *(C+i-1);
}
for (int *i = end-1; i > start-1; i--)
{
*(B+*(C+(*i))) = *i;
*(C+(*i)) -= 1;
}
return B;
}
In the last loop it throws an exception "Acces violation writing at location: -some ram address-"
Where did I go wrong?
for (int i = 1; i < maxvalue-1 ; i++)
That's the incorrect upper bound. You want to go from 1 to maxvalue.
for (int *i = end-1; i > start-1; i--)
{
*(B+*(C+(*i))) = *i;
*(C+(*i)) -= 1;
}
This loop is also completely incorrect. I don't know what it does, but a brief mental test shows that the first iteration sets the element of B at the index of the value of the last element in the array to the number of times it shows. I guarantee that that is not correct. The last loop should be something like:
int* out = B;
int j=0;
for (int i = 0; i < maxvalue; i++) { //for each value
for(j<C[i]; j++) { //for the number of times its in the source
*out = i; //add it to the output
++out; //in the next open slot
}
}
As a final note, why are you playing with pointers like that?
*(B + i) //is the same as
B[i] //and people will hate you less
*(B+*(C+(*i))) //is the same as
B[C[*i]]
Since you're using C++ anyway, why not simplify the code (dramatically) by using std::vector instead of dynamically allocated arrays (and leaking one in the process)?
std::vector<int>countSort(int* start, int* end, int maxvalue)
{
std::vector<int> B(end-start);
std::vector<int> C(maxvalue);
for (int *i = start; i < end; i++)
++C[*i];
// etc.
Other than that, the logic you're using doesn't make sense to me. I think to get a working result, you're probably best off sitting down with a sheet of paper and working out the steps you need to use. I've left the counting part in place above, because I believe that much is correct. I don't think the rest really is. I'll even give a rather simple hint: once you've done the counting, you can generate B (your result) based only on what you have in C -- you do not need to refer back to the original array at all. The easiest way to do it will normally use a nested loop. Also note that it's probably easier to reserve the space in B and use push_back to put the data in it, rather than setting its initial size.