boost multiarray segmentation fault - c++

I`m writing a code for which I'm using a 3 dimensional boost multiarray to save coordinates. But I always get a segmentation fault at some point.
How are boost multiarray sizes limited and how can I get around those limits?
Here is a simplified test code that reproduces the problem:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <boost/multi_array.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "Line.h"
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
typedef struct {
Eigen::Vector3d coords;
int gpHostZone;
int gpHostFace;
int calculated;
} Vertex;
class LGR {
public:
LGR (int i, int j, int k) :
grid(boost::extents[i][j][k])
{
};
std::string name;
std::vector<int> hostZones;
std::vector<int> refine;
boost::multi_array<Vertex*, 3> grid;
std::vector<double> data;
};
int main(void){
LGR lgr(11,11,21);
std::cout << lgr.grid.size();
std::vector<LGR> v;
std::vector<Vertex> vertexDB;
for(int i = 0; i < 1; i++ ){
for(int j = 0; j < lgr.grid.size(); j++ ){
for(int k = 0; k < lgr.grid[0].size(); k++ ){
for(int l = 0; l < lgr.grid[0][0].size(); l++ ){
Vertex coord;
coord.coords << i,j,k;
coord.gpHostZone = 0;
coord.gpHostFace = 0;
coord.calculated = 0;
vertexDB.push_back(coord);
lgr.grid[j][k][l] = &(vertexDB.back());
}
}
}
for(int j = 0; j < lgr.grid.size(); j++ ){
for(int k = 0; k < lgr.grid[0].size(); k++ ){
for(int l = 0; l < lgr.grid[0][0].size(); l++ ){
std::cout << "At ("<< i << ","<< j << ","<< k << "," << l << ")\n";
std::cout << lgr.grid[j][k][l]->coords<<"\n\n";
}
}
}
}
return 1;
}
Please do not comment on the includes. I just copy and pasted from the actual code. Most of the are probably not needed here. The dimensions are from a real example, so I actually need those kind of dimensions (and probably more).

The following is a definite issue that leads to undefined behavior, and doesn't have anything to do with boost::multiarray.
These lines:
std::vector<Vertex> vertexDB;
//...
vertexDB.push_back(coord);
lgr.grid[j][k][l] = &(vertexDB.back());
resizes the vertexDB vector and then stores a pointer to the last item in the vector to lgr.grid[j][k][l]. The problem with this is that pointers and iterators to items in a vector may become invalidated due to the vector having to reallocate memory when resizing the vector.
This manifests itself later here, in the subsequent loop:
std::cout << lgr.grid[j][k][l]->coords<<"\n\n";
There is no guarantee that the address you assigned previously is valid.
A quick fix for this is to use a std::list<Vertex>, since adding items to a std::list does not invalidate iterators / pointers.

Related

Getting random numbers on vector operation c++

I'm getting weird numbers as output in this code :
#include <iostream>
#include <vector>
int main(){
std::vector<std::vector<int>> vec = {{0,1},{2,3}};
vec.push_back({4,5});
vec.push_back({5,6});
for (int i = 0; i < vec.size(); i++){
for (int i2 = 0; i2 < vec.size(); i2++){
std::cout << vec[i][i2] << std::endl;
}
}
return 0;
}
It's returning to me:
0
1
1280136264
0
2
3
347673833
38962
4
5
297276653
134256690
5
6
280499436
268474418
I just want to know how to do it properly, and why I'm getting these numbers.
The output you are seeing is due to undefined behavior in your code.
The outer vector object has 4 inner vector<int> objects added to it. Each of those inner vector<int> objects is holding 2 int values.
Your inner for loop is going out of bounds of the inner vector<int> objects, by trying to access 4 int values when there are only 2 int values available.
In your inner for loop, you need to change vec.size() to vec[i].size() instead, eg:
#include <iostream>
#include <vector>
int main(){
std::vector<std::vector<int>> vec = {{0,1},{2,3}};
vec.push_back({4,5});
vec.push_back({5,6});
for (size_t i = 0; i < vec.size(); ++i){
for (size_t i2 = 0; i2 < vec[i].size(); ++i2){
std::cout << vec[i][i2] << std::endl;
}
/* alternatively:
auto &vec2 = vec[i];
for (size_t i2 = 0; i2 < vec2.size(); ++i2){
std::cout << vec2[i2] << std::endl;
}
*/
}
return 0;
}
Online Demo
That being said, a safer way to code this is to use range-for loops instead, eg:
#include <iostream>
#include <vector>
int main(){
std::vector<std::vector<int>> vec = {{0,1},{2,3}};
vec.push_back({4,5});
vec.push_back({5,6});
for (auto &vec2 : vec){
for (auto value : vec2){
std::cout << value << std::endl;
}
}
return 0;
}
Online Demo

main.exe has stopped working in code blocks

This is a code I wrote for bubble sort. I gave a comment //this line due to which I'm unable to run this program. Every time the first element of the array needs to be stored in 'temp'.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int arr[7]={7,8,5,2,4,6};
int temp;
for(int i=0;i<7;i++)
{
temp=arr[0]; //this line.
for(int j=0;j<7-i;j++)
{
if(temp<arr[j])
temp=arr[j];
else
swap(arr[j],arr[j-i]);
}
}
for(int k=0;k<7;k++)
{
cout<<arr[k]<<endl;
}
return 0;
}
There were some issue with your program:
Array size should be 6 instead of 7
The for loop condition was incorrect
swap(arr[j],arr[j-i]) will break when j-i is less than 0(for instance i=1, j=0).
Program
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int arr[6]={7,8,5,2,4,6};
for(int i=0;i<5;i++)
{
for(int j=0;j<5-i;j++)
{
if(arr[j]>arr[j+1])
swap(arr[j],arr[j+1]);
}
}
for(int k=0;k<6;k++)
cout<<arr[k]<<endl;
return 0;
}
Ideone
You seem flipped for() loops over... what I got - not the most elegant solution, but I stick to the same tools you're using. Mostly. I could make it as template and it would work with any appropriate container. std::sort sometimes implemented like that.
#include <iostream>
#include <algorithm>
void bubbleSort(int arr[], int n)
{
bool swapped;
for (int i = 0; i < n-1; i++)
{
swapped = false;
for (int j = 0; j < n-i-1; j++)
{
if (arr[j] > arr[j+1])
{
std::swap(arr[j], arr[j+1]);
swapped = true;
}
}
// no elements were swapped, array already sorted.
if (!swapped) break;
}
}
int main()
{
int arr[] = {7,8,5,2,4,6};
bubbleSort(arr, std::size(arr));
for( auto v : arr )
std::cout << v << " ";
std::cout << std::endl;
}
In C++11 and later <algorithm> can be replaced by <utility>, it's just for swap/size.

Complexity Reduction to O(n) Over Multiple Simultaeneous Vector Iteration

So I have 2 string vectors with the following content:
tokens: name name place thing thing
u_tokens: name place thing
Now my task is to simultaneously loop through both these vectors and find the occurrence of each word and store it in a third vector. Here's a minimal working implementation that I did (my task doesn't mention about duplicates so I did not consider removing it) :
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<int> counts;
vector<string> tokens;
vector<string> u_tokens;
tokens.push_back("name");
tokens.push_back("name");
tokens.push_back("place");
tokens.push_back("thing");
tokens.push_back("thing");
u_tokens.push_back("name");
u_tokens.push_back("place");
u_tokens.push_back("thing");
string temp;
int temp_count = 0;
for (int i = 0; i < tokens.size(); i++)
{
temp = tokens[i];
for (int j = 0; j < u_tokens.size(); j++)
{
if(temp == u_tokens[j])
{
temp_count++;
}
}
temp = tokens[i];
for (int k = 0; k < tokens.size(); k++)
{
if (temp == tokens[k])
{
temp_count++;
}
}
counts.push_back(temp_count);
temp_count = 0;
}
for (vector<int>::const_iterator i = counts.begin(); i != counts.end(); ++i)
cout << *i << " ";
return 0;
}
However, I noticed, this obviously has a O(n^2) complexity. How can I reduce it to O(n)? Is it possible?
Regards.
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
using namespace std;
void CountOccurences(const vector<string>& input, unordered_map<string, size_t>& occurences)
{
for (int i = 0; i < input.size(); i++)
{
occurences[input[i]]++;
}
}
int main()
{
vector<string> tokens;
vector<string> u_tokens;
unordered_map<string, size_t> occurences;
tokens.push_back("name");
tokens.push_back("name");
tokens.push_back("place");
tokens.push_back("thing");
tokens.push_back("thing");
u_tokens.push_back("name");
u_tokens.push_back("place");
u_tokens.push_back("thing");
CountOccurences(tokens, occurences);
CountOccurences(u_tokens, occurences);
for (auto i : occurences)
cout << i.first << "=" << i.second << " ";
return 0;
}
Use std::unordered_map as O(1) access container to create O(N) solution. In cost of memory of course.
Link to online compiled program

Size of a vector of pairs

I am filling up an adjacency list of vector with pairs given by :
vector<pair<int, int>> adj[1000];
I am doing a depth first search on the list but experiencing some weird behaviour. The first print statement prints some value which means I have some items in adj[s][0], adj[s][1], adj[s][2] and so on. However when I calculate the size of adj[s] in the next line it prints out to be zero. Am I missing something here?. Is my definition for vector of pairs correct?. The adjacency list is correctly filled because when I ran cout << adj[s][0].first << endl; in dfs, it was correctly showing me the neighbors of each and every node.
Complete code
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <utility>
#include <climits>
#include <algorithm>
using namespace std;
vector<pair<int, int>> adj[1000];
bool visited[1000];
int nodeweight[1000];
void initialize()
{
for(int i = 0; i < 1000; i++)
visited[i] = false;
for(int i=0; i < 1000; i++)
adj[i].clear();
for(int i = 0; i <1000; i++)
nodeweight[i] = INT_MAX;
}
void dfs(int s)
{
visited[s] = true;
cout << adj[s][1].first << endl;
int minimum = INT_MAX, tovisit = 0;
for(int i = 0; i < adj[s].size(); i++)
{
cout << adj[s][i].second;
if(!visited[adj[s][i].first] && adj[s][i].second < minimum)
{
minimum = adj[s][i].second;
tovisit = adj[s][i].first;
}
}
nodeweight[tovisit] = minimum;
//dfs(tovisit);
}
int main() {
int N, E;
cin >> N >> E;
while(E--)
{
int i, j, w;
cin >> i >> j >> w;
adj[i].push_back(make_pair(j,w));
adj[j].push_back(make_pair(i,w));
}
initialize();
for(int i = 1; i <= N; i++)
{
dfs(i);
}
return 0;
}
You are clearing adj again after filling in initialize().
First you fill adj in the while loop in main. Then you call initialize() which includes this loop clearing all vectors in it:
for(int i=0; i < 1000; i++)
adj[i].clear();
Then you have cout << adj[s][1].first << endl; in dfs which is undefined behavior because there are no elements in adj[s]. The fact that you seem to get the correct results is just coincidental undefined behavior (although practical it is because the memory holding the vector data was not cleared.)
adj[s].size() is correctly reported as 0.

c++ output increasing numbers

Hi I have an array of share prices but I only want to output them as they increase.
For example if I have 1,1,1,2,2,2,3,3,3,4,4,4,5,5,5, etc. I only want to print 1,2,3,4.
I have tried setting a temporary max and min but still can't get it.
Now I only have this:
for(int h = 0; h < max; h++)
{
if(v3[h].getPrice() > 0)
{
ofile << v[h].getPrice() << ", ";
}
}
What you want is this
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
// Assign your vector
int a[] = {1,1,1,2,2,3,3,3,4,4,5,5,5,1,3};
vector<int> vec(a, a+15);
// Sort before calling unique
sort(vec.begin(), vec.end());
// Impose only one of each
vector<int>::iterator it;
it = unique(vec.begin(), vec.end());
vec.resize( distance(vec.begin(),it) );
// Output your vector
for( vector<int>::iterator i = vec.begin(); i!= vec.end(); ++i)
cout << (*i) << endl;
return 0;
}
Live example
The sort is necessary for unique to work.
#include <iostream>
using namespace std;
int main()
{
int a[15] = {1,1,1,2,2,2,3,3,3,4,4,4,5,5,5};
for (int i=0; i<15; i+=3)
{
cout << a[i] <<",";
}
return 0;
}
Increment the counter 3 times in the loop " for(int h=0;h < max; h+=3){} ".