Getting SIGESV error in following cpp code [duplicate] - c++

This question already has answers here:
Segmentation Fault (SIGSEGV) when getting data as input in the vector of struct
(2 answers)
Closed 2 years ago.
Getting SIGESV error in following cpp code, kindly check.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, m;
int sa = 0, sb = 0, c = 0;
cin >> n >> m;
vector<int> a;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<int> b;
for (int i = 0; i < m; i++) {
cin >> b[i];
}
int k = min(n, m);
while (k--) {
sa = accumulate(a.begin(), a.end(), 0);
sb = accumulate(b.begin(), b.end(), 0);
if (sb >= sa) {
swap(*min_element(a.begin(), a.end()),
*max_element(b.begin(), b.end()));
c++;
} else {
break;
}
}
if (sb >= sa) {
cout << "-1" << endl;
} else {
cout << c << endl;
}
}
return 0;
}
The code asks for two arrays and swaps only if array a has a summation less than array b.
Getting error as SIGESV, also can take 'b' array as an input, what to do?

When you're doing cin >> a[i], a is still empty, so attempting to access its i-th element produces a segfault. Resize it before with a.resize(n) or initialise it with the proper size: vector<int> a(n);

The size and capacity of vector a is 0 and never changes.
This code is broken:
vector<int> a;
for(int i=0;i<n;i++){
cin>>a[i];
}
operator[]() does not grow the vector. You are assigning values to memory that does not belong to a.
You want a.push_back(i) at a minimum. What you probably really want is:
vector<int> a;
a.reserve(n);
for (int i = 0; i < n; ++i) {
int tmp;
cin >> tmp;
a.push_back(tmp);
}
Reserving memory stops the vector from re-allocating. Not doing it in a constructor also stops default initialization of all elements.
The same goes for the b vector.
You also never change the values of sa or sb, but that shouldn't crash anything, it's just a logic error from what I can see.
The file as a whole is also rife with bad practices. "Competitive" coding sites actively make you a worse programmer.

When you know size you need while declaring vector you should declare vector like this
vector<int>arr(n);
vector<int>arr2(m);
this will create an vector of size n will value being zero at all indexes in vector at initialization.
Don't use <bits/stdc++.h> and trying coming up for better name for variables it will really help you as well as us. I know this is compeitive programming question but still.

Related

c++ runtime error when using vectors push back and iterator

Hi I'm trying to solve a algorithm problem and when I submit my code on an online judge I keep on getting a runtime error. I have no idea why it is happening.
Here is the problem that I'm trying to solve.
The code is as follows. It works fine for the sample input and outputs in visual studio. I haven't yet met inputs and outputs that does not work well or actually meet the runtime error. Only the online judge is giving the runtime error so I can't figure out why.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int m;
int c1;
int c2;
cin >> n >> m >> c1 >> c2;
vector<int> p = {};
vector<int> q = {};
for (int i = 0; i < n; ++i)
{
int temp;
cin >> temp;
p.push_back(temp);
}
for (int i = 0; i < m; ++i)
{
int temp;
cin >> temp;
q.push_back(temp);
}
vector<int> distance = {};
for (int i = 0; i < p.size(); ++i)
{
for (int j = 0; j < q.size(); ++j)
{
distance.push_back(abs(p[i] - q[j]) + abs(c1 - c2));
}
}
sort(distance.begin(), distance.end());
int min = distance[0];
int count = 0;;
for (int i = 0; i < static_cast<int>(distance.size()); ++i)
{
if (distance[0] == distance[i])
count++;
else
break;
}
cout << min << " " << count << endl;
return 0;
}
If n and m are both the maximum allowed value of 500,000 then distance will have 500,000 * 500,000 elements which will use 1TB of memory. Due to vector growing as you push_back you could actually need around 2TB of memory in total. The online judge presumably doesn't allow you to use this much memory.
If you rethink your algorithm to not store the values of distance it will probably work.
You should lways use reserve on std::vector if you know the size in advance as it should cause the vector to allocate exactly the right amount of memory and avoid copying to new blocks of memory as the vector grows.

bad alloc exception when trying to resolve BFS challenge on HackerRank

So i was trying to make the challage: Breadth First Search: Shortest Reach on HackerRank, but i keep getting the bad alloc exception when the tests have great numbers of node/edges. The program works on the first test, so i don't think, it's something wrong with the implementation.
So here is the implementation:
(sorry for the indentation , my first question)
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <limits.h>
using namespace std;
int main() {
//test numbers
int t;
//the cost
int cost = 6;
cin >> t;
//for each test
for (int nt = 0; nt < t; ++nt) {
int n, e;
int snode;
queue <int> *que = new queue<int>();
//read the node/edges
cin >> n >> e;
//distance/visited/parents arrays/adjlist vector
int dist[n + 1] = {-1};
bool visited[n + 1] = {false};
int parents[n + 1] = {-1};
vector< vector<int> > adjList(n + 1);
//read into the adjlist, unoriented graph, each edge has 6 weight
for (int ne = 0; ne < e; ++ne) {
int x, y;
cin >> x >> y;
adjList[x].push_back(y);
adjList[y].push_back(x);
}
//read the starting node
cin >> snode;
dist[snode] = 0;
//do actual bfs
que->push(snode);
visited[snode] = true;
while(!que->empty()) {
int c_node = que->front();
que->pop();
for (int i = 0; i < adjList[c_node].size(); ++i) {
if (visited[adjList[c_node].at(i)] == false) {
que->push(adjList[c_node].at(i));
parents[adjList[c_node].at(i)] = c_node;
dist[adjList[c_node].at(i)] = dist[parents[adjList[c_node].at(i)]] + cost;
visited[adjList[c_node].at(i)] == true;
}
}
}
//print at output the distance from the starting node to each other node
//if unreachable, print -1
for (int i = 1; i < n + 1; ++i) {
if (i == snode) {
} else if (dist[i] == 0 && i != snode) {
cout << "-1 ";
} else {
cout << dist[i] << " ";
}
}
cout << "\n";
}
return 0;
}
Am i doing something wrong, i haven't seen anyone else complain on this matter in the discussion section of the site.
How can i avoid the exception to be thrown and from where does it come?
Thank you!
I don't know, exactly, what is the cause of your exception; and I don't know ho to reproduce your problem because depends (I suppose) from the input values. A lot of input values, I suppose.
But I see some weak points (IMHO) of your code, so I try to point your attention to them.
1) you alloc a std::queue in your for cycle
queue <int> *que = new queue<int>();
but you never free it; it's a waste of memory
2) you're using C-style variable-length arrays
int dist[n + 1] = {-1};
bool visited[n + 1] = {false};
int parents[n + 1] = {-1};
They aren't valid C++ standard code. I suggest you the use of standard containers (std::vector or std::queue).
3) you're initializing your C-style variable-length arrays with a initializers lists with only an element (-1 or false). I suppose your intention was initialize all n+1 elements with -1 and false. But this syntax initialize only the first element of the array with -1 and false.
If you want to initialize all n+1 element to -1 and false, the solution is (again) use standard containers; by example
std::vector<int> dist(n+1, -1);
std::vector<bool> visited(n+1, false);
std::vector<int> parents(n+1, -1);
4) you access arrays without bounds checking. By example:
cin >> snode;
dist[snode] = 0;
where snode is a int variable; if you insert a negative value, or a value over n, you write dist out of its bounds, devastating the memory. This, I suppose, can explain your "bad alloc exception".
Suggestion: use standard containers (again) instead of C-style array and use at() (that perform bounds checking) instead []; so
cin >> snode;
dist.at(snode) = 0;
5) sorry for my bad English (ok, I'm joking: this isn't one of your weak points; this is one of mine).

Boolean array getting unexpected default values

I wrote the following C++ program to implement breadth first search to solve this problem of finding shortest path for all the nodes from the source.
#include<iostream>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;
int main()
{
int test;
cin >> test;
while(test--)
{
int m,n,source;
cin >> n >> m;
bool visited[n+1];
int dist[1001];
queue<int> q;
memset(dist, -1, sizeof(dist));
vector<int> adj[1001];
for(int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
cin >> source;
dist[source] = 0;
visited[source] = true;
q.push(source);
while(q.size())
{
int v = q.front();
q.pop();
for(int i : adj[v])
{
if(!visited[i])
{
q.push(i);
dist[i] = dist[v] + 6;
visited[i] = true;
}
}
}
for(int i = 1; i <= n; i++)
{
if(i != source)
{
cout << dist[i] << " ";
}
}
cout << "\n";
}
}
It works well if the value of test is 1, but when the value is 2 or more, some values of the boolean array "visited" become 1 in the second and later iterations. I do not understand why and how it happens as I declare the boolean array in every iteration and the default value for its elements is 0. Can somebody please explain this.
I declare the boolean array in every iteration and the default value for its elements is 0.
No, it's not 0. There are no default values for C++ simple types. My bet is you propably get some random values, as your array isn't initialised automatically.
You aren't initialising the array, and local arrays are not zero initialised, so explicit initialisation is needed.

c++ vector array error

int main()
{
int n, inInt;
vector <int> list;
ifstream ifs("1.txt");
float a;
ifs >> a;
std::vector<int> result;
int temp;
while(! ifs.eof())
{
ifs >> temp;
result.push_back(temp);
}
int b;
b = result.size();
float array[b+1];
int i;
array[0] = a;
for(i = 1;i < b+1;i++) {
array[i] = (array[i-1] + result[i]-2*array[i-1] * result[i]/a);
}
cout << array[b];
system("pause");
return 0;}
Basically in my code, I built a vector and build an array and try to use the data from the vector in the array.However,when I text the code,it gave me a huge incorrect number.
temp is not an array, temp is an int. You're trying to use operator[] on an int you cannot do that. Also, VLAs (Variable Length Arrays) are a GCC extension, and therefore not standard. I suggest you replace this line:
float array[b+1];
With:
std::vector<float> array(b+1);
I see at least two problems. First, your input loop is incorrect and inserts an invalid entry into result. You can fix this by using the following input loop:
while (ifs >> temp)
{
result.push_back(temp);
}
Second, the vector result contains b elements so the valid indices are [0..b-1]. Your loop end condition i < b+1 will read one element past the end of result. I think you can fix this issue by doing this instead:
for(i = 0; i < b; i++)
{
array[i+1] = (array[i] + result[i]-2*array[i] * result[i]/a);
}
When I made these changes and used 3 2 2 for input, the output was 1.66667

2D Dynamic Array C++ Display Problem

I've read about 2d dynamic arrays but I obviously haven't quite got my head around it as this program doesn't work. The program seems to lie in displaying the array.
The input file is a text file with V and E on the first line with a 'tab indent' between them. The input vertices are on the next lines again tab indented with a new set on each line. On DevCpp it says there is a segmentation fault. Any help would be very much appreciated. thanks.
#include <iostream>
#include <fstream>
using namespace std;
#define maxV 100
#define unseen 0
typedef int Vertex;
class Graph {
private:
int V, E;
int**adj;
public:
Graph(char filename[]);
void display();
};
// constructor ask you for file name
Graph::Graph(char fname[]) {
Vertex u,v;
int j;
ifstream f;
f.open(fname, ios::in);
if(!f) {
cout << "\nError: Cannot open file\n";
return;
}
//Input number of vertices and edges
f >> V >> E;
int** adj = new int*[V];
for (int i=0;i<=V;i++)
{
adj[i]= new int[V];
}
for(int x=0;x<=V; ++x) // initially 0 array
{
for (int y=0;y<=V;++y)
adj[x][y] = 0;
}
// Set diagonal to 1
for(int z=0; z<=V; ++z)
adj[z][z]=1;
for (j =0;j<=E;++j)
{
f>>u>>v;
adj[u][v] = 1;
adj[v][u] = 1;
}
}
// This method displays the adjacency lists representation.
void Graph::display(){
int a,b,c;
for (a=0;a<=V;++a)
{
cout << a << " ";
}
cout << endl;
for (b=0;b<=V;++b)
{
cout << b << "| ";
for (c=0;c<=V;++c)
{
cout<<adj[b][c]<<"| ";
}
cout<<endl;
}
}
int main()
{
char fname[20];
cout << "\nInput name of file with graph definition: ";
cin >> fname;
Graph g(fname);
g.display();
}
//Input number of vertices and edges
f >> V >> E;
// You're hiding your member variable in the following line, leading to an incorrect initialization
// int** adj = new int*[V];
adj = new int*[V];
for (int i=0;i<=V;i++)
{
adj[i]= new int[V];
}
I see two significant problems just in the code that initializes the data array. First, a loop like this
for (int i=0;i<=V;i++)
loops over one more element than actually exists in the array. The correct form of a loop if the array is V elements long is
for (int i=0;i<V;i++)
That's "less than" rather than "less than or equal".
Secondly, you allocate both the array of pointers to be V pointers long, and than the individual columns to be V elements long as well; but later you use the same array and expect it to be V x E in size. Altogether, then, I think the allocation code ought to be
int** adj = new int*[V];
for (int i=0;i<V;i++)
{
adj[i]= new int[E];
}
There are likely to be other errors elsewhere, but at least I've got you started.
I don't know which line is causing the segmentation fault but here are some things to look at:
for (j =0;j<=E;++j)
{
f>>u>>v;
adj[u][v] = 1;
adj[v][u] = 1;
}
Are u and v guaranteed to be less than V? If not you could be writing outside the bounds of the matrix.
What happens when j == E? You are trying to read a line past the last line in the file. You should be checking instead for j < E. A better way still would be to ignore E all together and just do this:
while(f >> u >> v)
{
adj[u][v] = 1;
adj[v][u] = 1;
}
More likely though the segmentation fault is here:
for (b=0;b<=V;++b)
{
cout<<(b+1)<<"| ";
for (c=0;c<=V;++c)
{
cout<<adj[b][c]<<"| ";
}
cout<<endl;
}
the for loop conditionals should be checking b < V and c < V not <=. when either b or c == V you are definitely reading outside the matrix.