c++ 2d array leads to Segmentation fault (core dumped) - c++

I have a program (below) to build a matrix of distances between points (in my test file there are ~8000 points in 3D space). So I want a (roughly) 8000x8000 matrix, but when I try to build it using an array of doubles (or floats), I always get a 'Segmentation fault (core dumped)' error. Any ideas why? I have 16GB of RAM, so this should be feasible, since 8000 * 8000 * 8 is only roughly 0.5GB. Also (commented out in code below), I can build the matrix as a vector of vectors, but this is slow - takes around 30 seconds. As it happens, I only need to record distances less than 1.5, so the matrix is very sparse - no doubt there are better ways of implementation, but it's bugging me that this doesn't work. Any advice gratefully received!
//Get distance matrix from .dms file
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
using namespace std;
double dist(vector<double> a, vector<double> b) {
if (a.size() != b.size()) return -1;
else
{
double dist = 0;
for (int i = 0; i < a.size(); i++) dist += pow(a[i] - b[i], 2);
return dist;
}
}
int main() {
ifstream infile;
ofstream outfile;
vector<vector<double> > points;
string line;
infile.open("1dwr.dms");
outfile.open("1dwr.mat");
while (getline(infile,line))
{
if ((line.at( line.length() - 1)) != 'A')
{
double x[3] = {atof((line.substr(13,8)).c_str()), atof((line.substr(21,9)).c_str()), atof((line.substr(30,9)).c_str())};
vector<double> point;
for (int i=0; i<3; i++)
{
point.push_back(x[i]);
}
points.push_back (point);
}
}
infile.close();
int len = points.size();
double dist_matrix[len][len];
for (int i=0; i<len; i++)
{
for(int j=i; j<len; j++)
{
double d = dist(points[i], points[j]);
if(d < 2.25)
{
dist_matrix[i][j] = sqrt(d);
dist_matrix[j][i] = sqrt(d);
}
}
}
// vector<vector<double> > dist_matrix;
// for (int i=0; i<len; i++)
// {
// vector< double> row;
// for (int j=0; j<len; j++)
// {
// double d = dist(points[i], points[j]);
// if (d < 2.25) row.push_back (sqrt(d));
// else row.push_back (0);
// }
// dist_matrix.push_back (row);
// }
outfile.close();
return 0;
}

The problem is that statements int len = points.size(); double dist_matrix[len][len] lets the program create a 8000 x 8000-array of doubles on the stack, and the size of the stack is - compared to the heap - rather limited. So it is very likely that you get a "stack overflow", indicated probably by a "Bad access"-error. If you try your code with 80x80, it will probably work.
So for len==8000, you'd have to create the array on the heap; yet there is - to my knowledge - no way to do a statement like double x[len][len] = new double... if len is not known at compile time.
You could come around this by allocating a 1D-array of size len * len and calculate the "2D"-index manually, as shown in the code below:
int main() {
int len = 8000;
double *dist_matrix = new double[len*len];
for (int i=0; i<len; i++)
{
for(int j=i; j<len; j++)
{
size_t idx = len*i + j;
dist_matrix[idx] = 5.0;
}
}
return 0;
}

Related

double recursion segmentation fault c++

I've recently written this quicksort sorting algorithm. After compiling I get a "segmentation fault (core dumped)". I debugged it and it turned out that line 25 causes the problem:
v2 = quicksort(v2);
However, I do not know why I get a the "core dumped", as I have no idea what's the problem with this line.
Here's my code:
#include <iostream>
#include <vector>
#include <random>
using namespace std;
vector <float> quicksort(vector <float> Vec)
{
if(Vec.size() > 1)
{
float pivot = Vec[(Vec.size())/2-1];
vector <float> v1, v2;
vector <float> V;
for(unsigned int i = 0; i < Vec.size(); i++)
{
if(Vec[i] >= pivot)
v2.push_back(Vec[i]);
else
v1.push_back(Vec[i]);
}
v1 = quicksort(v1);
v2 = quicksort(v2);
//after debuggung, I found out that the line above causes the "segmentation fault (core dumped)" (line 25)
for(unsigned int i = 0; i < v1.size(); i++)
V.push_back(v1[i]);
for(unsigned int i = 0; i < v2.size(); i++)
V.push_back(v2[i]);
return V;
}
else
{
return Vec;
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
vector <float> v;
for(int i = 0; i < 100; i++)
{
v.push_back(rand() % 100);
cout << v[i] << " ";
}
v = quicksort(v);
for(int i = 0; i < 100; i++)
{
cout << v[i] << " ";
}
return 0;
}
Thanks for the help.
First of all, to get a totally random number using rand() you need to seed the number generator. To do this you include the "time.h" library and then write: srand (time(NULL));
Secondly, your quicksort takes two parameters, a vector named Vec and an int f, that isn't used for anything. Take int f of the function's parameters.
Thirdly, the problem is that an infinite loop is happening in this part of the code (lines 17 to 23):
for(unsigned int i = 0; i < Vec.size(); i++){
if(Vec[i] >= pivot)
v2.push_back(Vec[i]);
else
v1.push_back(Vec[i]);
}
Imagine that our Vec vector is {2, 3} (this were the actual values, because we didn't seed the random number generation).
What's happening is that we have our pivot = 2, and then we are saying that if Vec[0], which is 2, is bigger or equal than the pivot, we add Vec[0] to v2, and then the same for Vec[1], which is 3.
Then this loops infinitely, because then you say v2 = quicksort(v2);. That will make Vec = v2. And that means that it will never get smaller, because, again, Vec is {2, 3}, and therefore our pivot = 2.
It goes in stack overflow.
If the pivot is the maximum number of the vector Vec it has to be dragged from Vinf into Vsup.
#include <iostream>
#include <vector>
#include <random>
using namespace std;
vector <float> quicksort(vector <float> Vec) { //the int f was never used un the function
if (Vec.size() > 1){
vector <float> Vinf, Vsup, Vtmp;
Vinf.push_back(Vec[(Vec.size()) / 2 - 1]);
float pivot = Vinf[0];
Vec.erase(Vec.begin() + Vec.size() / 2 - 1);
for (unsigned int i = 0; i < Vec.size(); i++)
Vec[i] > pivot ? Vsup.push_back(Vec[i]) : Vinf.push_back(Vec[i]);
if (Vinf.size() == Vec.size() + 1) {
Vsup.push_back(pivot);
Vinf.erase(Vinf.begin());
}
Vinf = quicksort(Vinf);
Vsup = quicksort(Vsup);
for (unsigned int i = 0; i < Vinf.size(); Vtmp.push_back(Vinf[i++]));
for (unsigned int i = 0; i < Vsup.size(); Vtmp.push_back(Vsup[i++]));
return Vtmp;
}
else
return Vec;
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
vector <float> v;
for (int i = 0; i < 100; cout << v[i++] << " ")
v.push_back(rand() % 100);
cout << endl;
v = quicksort(v);
for (int i = 0; i < v.size(); cout << v[i++] << " ");
return 0;
}

writing to 2D vector, is crashing my program

I'm new to vectors programming, so my code is buggy:
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
std::ifstream in("input.txt");
std::vector<std::vector<int> > v, w;
if (in) {
std::string line;
while (std::getline(in, line)) {
v.push_back(std::vector<int>());
for(int x=0; x<line.size(); x++){
v.back().push_back((int)line[x] - (int)'0');
}
}
}
for (int i = 0; i < v.size(); i++) {
for (int j = 0; j < v[i].size(); j++)
std::cout << v[i][j] << ' ';
std::cout << '\n';
}
int size = v.size(); //because its a square matrix
w = v; //w is our temp vector for storing new values;
int alive =0;
int z=0;
for (int i=0;i<size;i++)
{
for (int j=0;j<size; j++)
{
alive = 0;
for(int c = -1;c<2; c++)
{
for(int d = -1; d<2 ; d++)
{
if(!(c==0 && d == 0))
{
z = v[i+c][j+d];
if(z)
++alive;
}
}
if(alive<2) w[i].push_back(0);
else if(alive == 3) w[i].push_back(1);
else w[i].push_back(0);
}
}
}
return 0;
}
I think I am assigning values into my second variable wrong. My program reads from an input file along the lines:
1010101
0101010
1010101
and is to write to the second vector w after analyzing its neighbors (game of life problem), I think I should use w.push_back() but I'm not sure on the syntax for a 2D vector. Is there a better way to push the variable?
There are two problems that I notice right away. The main one that is causing your crash is you are accessing outside of the bounds for the v array. This happens when i is 0 and c is -1, and can also happen when i is size-1 and c is +1 (the same thing happens with j and d).
The other issue is with how you save the alive value into w. Since you start with w = v, you have all the elements you need. Just replace them with, for example, w[i][j] = 0. (You'll also want to move that conditional block outside of the c loop.)

How to run this code in less than 1 second?

How can I solve this problem without getting time limit exceeded
http://codeforces.com/problemset/problem/474/B
I tried putting all ranges in a 2D vector then looking for the desired index using binary search but it seems that the loop in the fn BS() takes a lot to execute as the size of the vector can be 10^6.
here is my code:
#include <iostream>
#include <vector>
using namespace std;
int Search(vector <vector<int> > a,int key){
int start = 0;
int end = a.size() - 1;
while (start <= end){
int mid = start + (end - start) / 2;
if (a[mid][0] > key && a[mid][1] > key){
end = mid - 1;
}
else if (a[mid][0] < key && a[mid][1] < key){
start = mid + 1;
}
else {
return mid;
}
}
return -1;
}
vector <int> BS(vector <vector <int> > v, vector<int> keys){
int j = 0;
vector <int> piles;
for (int i = 0; i < keys.size(); i++){
piles.push_back(Search(v, keys[i])+1);
}
return piles;
}
vector < vector<int> > Range(vector<int> v){
vector < vector<int> > ranges(v.size());
int sum1 = 1;
int sum2 = v[0];
for (int i = 0; i < v.size(); i++){
if (i == 0){
ranges[i].push_back(sum1);
ranges[i].push_back(v[i]);
sum1 += v[i];
}
else{
ranges[i].push_back(sum1);
sum2 += v[i];
ranges[i].push_back(sum2);
sum1 += v[i];
}
}
return ranges;
}
int main(){
int n, m;
cin >> n;
vector <int> a, q;
vector < vector <int> > v;
for (int i = 0; i < n; i++){
int k;
cin >> k;
a.push_back(k);
}
cin >> m;
for (int i = 0; i < m; i++){
int l;
cin >> l;
q.push_back(l);
}
v = Range(a);
vector <int> jucy = BS(v, q);
for (int i = 0; i < jucy.size(); i++){
cout << jucy[i] << endl;
}
}
In fact i don`t think you need 2D vector at all, you need just 1D. Which for example would look like this [2,9,12,16,25], the upper bound of each pile, you can construct this really easy. Then for every juicy worm you do binary search in that manner that it returns index with value greater or equal to the value you are looking for. The index you got from the search is the pile you are looking for.
Some pseudo-code:
A[n] - vector of upper bounds
A[0] = a0
For each 0<i<=n A[i]=A[i-1]+ai
For each q do std lower_bound on A looking for q,
the index you get is with first value equal or greater than q, so the pile where is q.
and C++ code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
int n, m;
cin >> n;
vector<int>A;
A.resize(n);
int ai;
cin >> ai;
A[0]=ai;
for (int i = 1; i < n; i++){
cin >> ai;
A[i]=A[i-1]+ai;
}
cin >> m;
int q;
for (int i = 0; i < m; i++){
cin >> q;
cout << std::distance(A.begin(),std::lower_bound(A.begin(),A.end(),q))+1<<endl;
}
return 0;
}
You have to add +1 to distance because the piles are numbered from 1. Work for the example, and looks pretty fast.
The most obvious optimization opportunity is, instead of using a vector<vector<int>> use a vector<int> and manually adjust the 2D indices to 1D. You can write a simple wrapper class that does this for you.
The reason that that will be much faster is that then all the memory will be allocated as a single contiguous unit. If you have a vector of vectors, then each row will be somewhere else and you'll have lots of cache misses.
Here's a code example:
struct 2D_Vector {
std::vector<int> me_;
int ncols_;
2D_Vector(int nrows, int ncols) : me(nrows * ncols), ncols_(ncols) {}
int & get(int y, int x) { return me_[y * ncols_ + x]; }
const int & get(int y, int x) const { return me_[y * ncols_ + x]; }
...
};
If you preallocate this with all the space that it will need, then it should use memory very efficiently.
Also, passing large function parameters by value instead of by reference is very wasteful, because it results in needless copies being made and destroyed. (Like WhozCraig pointed out.)

Problems with Floyd-Warshall algorithm implementation

I was trying to sole the second problem from the INOI 2014 paper ie. FREETICKET and used Floyd-Warshall algorithm to compute the answer. My code appears to fail in the final subtask and appears to give WA for a couple test cases.The code follows:
#include <iostream>
#include <cstdio>
#include <climits>
#include <vector>
#include <algorithm>
using namespace std;
typedef vector<long long int> vl;
typedef vector<vl> vvl;
long long int maxelem(const vvl& arr)
{
long long int max = 0, curmax;
for(int i = 0, l = int(arr.size());i < l;i++)
{
curmax = *(max_element(arr[i].begin(), arr[i].end()));
if(curmax > max)
{
max = curmax;
}
}
return max;
}
int main(void)
{
long long int c, f, x, y, p;
scanf("%lld%lld", &c, &f);
vvl adj(c, vl(c, 26336));
for(int i = 0;i < f;i++)
{
scanf("%lld%lld%lld", &x, &y, &p);
adj[x-1][y-1] = p;
adj[y-1][x-1] = p;
}
long long int max = 0;
for(int k = 0;k < c;k++)
{
for(int i = 0;i < c;i++)
{
for(int j = 0;j < i;j++)
{
adj[i][j] = min(adj[i][j], adj[i][k] + adj[k][j]);
}
for(int j = (i + 1);j < c;j++)
{
adj[i][j] = min(adj[i][j], adj[i][k] + adj[k][j]);
}
}
}
max = maxelem(adj);
printf("%lld\n", max);
}
This code just uses an adjacency matrix and ensures that the guy doesn't try to go from the same place, to the same place(in the innermost loop). It fails to solve some of the subtasks from subtask 3 and yields me 50/100 marks. Can anyone help me finding the bug in my code ? I have even tried changing the data type to long long int's.(Just to be safe).
The problem for your algo is:
for(int i = 0;i < f;i++)
{
scanf("%lld%lld%lld", &x, &y, &p);
adj[x-1][y-1] = p;
adj[y-1][x-1] = p;
}
It should be:
for(int i = 0;i < f;i++)
{
scanf("%lld%lld%lld", &x, &y, &p);
adj[x-1][y-1] = min(p, adj[x-1][y-1]);
adj[y-1][x-1] = min(p, adj[y-1][x-1]);
}
Because, if there are multiple routes between city a -> b, we just need to take the cheapest route.
And you also need to set each adj[i][i] = 0 for all 0 <= i < c

C++ Strange std::bad_alloc exception

So I have the following code:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int MAXN = 1000000;
int isNotPrime[MAXN];
vector<int> primes;
void sieve()
{
for(int i = 2; i <= sqrt(MAXN); ++i)
{
if(isNotPrime[i]) continue;
for(int j = i*i; j <= MAXN; j += i)
{
isNotPrime[j] = true;
}
}
for(int i = 2; i <= MAXN; ++i)
{
if(!isNotPrime[i])
{
primes.push_back(i);
}
}
}
int main()
{
ios::sync_with_stdio(false);
sieve();
return 0;
}
What I cannot understand is why my program throws a std::bad_alloc exception when it executes. Even more mind-boggling is that when I swap the lines int isNotPrime[MAXN]; and vector<int> primes; the programs executes as intended.
Swapped like this:
vector<int> primes;
int isNotPrime[MAXN];
The problem is here:
for(int i = 2; i <= MAXN; ++i)
The check should be i < MAXN instead. (Or, make the array have size MAXN + 1.)
At some point, the isNotPrime[MAXN] = true; executes, which overflows the bounds of the array, causing undefined behaviour. In practice, this overwrites some internal field of the next variable (primes), which confuses the std::vector implementation, probably causing it to request a lot of memory.
This also explains why switching the variable order "fixes" it, because now you're scribbling over something else instead of primes.