C++ Strange std::bad_alloc exception - c++

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.

Related

How to improve my code so that it wouldn't terminate due to timeout?(HackerRank challenge)

My code works pretty well, but when I submit it on HackerRank, it shows me the error of "Your code did not execute within the time limits" for a few cases, and "success" for the rest of the cases.
Here's the link to the HackerRank challenge and what the code is required to do:
https://www.hackerrank.com/challenges/circular-array-rotation/problem
Here's my code:
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
int n, k, q, count=0, index;
cin>>n>>k>>q;
int ar[n];
for (int i = 0; i < n; i++)
{
cin>>ar[i];
}
int m[q];
for (int i = 0; i < q; i++)
{
cin>>m[i];
}
while (count != k)
{
for (int i = n-1; i > 0; i--)
{
swap(ar[i],ar[i-1]);
}
count++;
}
for (int i = 0; i < q; i++)
{
index=m[i];
cout<<ar[index]<<endl;
}
return 0;
}
How about considering setting the starting point of the array to a variable, and calculate this variable to avoid loops.Maybe many loops or int ar[n](I don't know the oj if it supports).
and the solution may like:
for(...){
++pos;
if (pos == k) pos = 0;
}
so what you should do is output the array from pos to end,and 0 to pos
You are doing it in O(N*N) but it can be done in O(N). So I request you to go through this https://www.geeksforgeeks.org/array-rotation/. In case any doubts comment them down.

Logical error in a C++ selection sort algorithm?

I'm brand new to C++ and am trying to write this simple selection sort function. Apologies if the answer is simple to the more experienced coders, but I am beginner and have been staring at this for a long time to no avail. Here is my code:
#include <iostream>
#include <array>
using namespace std;
array<int, 10> unsorted {3, 4, 1, 5, 7, 2, 8, 9, 6, 0};
void printarray(array<int, 10> arr) {
int count = 0;
for (int i : arr) {
if (count < arr.size()-1) {
cout << i << ", ";
} else {
cout << i << endl;
}
count++;
};
}
int selection_sort(array<int, 10> arr) {
int test;
array<int, 10> newarr;
for(int j = 0; j < arr.size(); j++) {
test = arr[j];
for(int i = j; i < arr.size(); i++) {
if(arr[i+1] < test) {
test = arr[i];
}
}
newarr[j] = test;
}
printarray(newarr);
return 0;
}
int main() {
selection_sort(unsorted);
return 0;
}
When I run this function it prints an int array containing 10 zeros. Is there an error with the way I am assigning values to the array (in C++), or rather is there a problem with the logic itself?
Both of the implementations are wrong. I just corrected #Adrisui3's answer.
Correct solution:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> array(5);
int aux;
array[0] = 10;
array[1] = 2;
array[2] = 45;
array[3] = -5;
array[4] = 0;
for(int i = 0; i < array.size(); i++)
{
int min = i;
for(int j = i+1; j < array.size(); j++)
{
if(array[j] < array[min])
{
min = j;
}
}
if (i != min)
{
aux = array[i];
array[i] = array[min] ;
array[min] = aux;
}
}
for(int k = 0; k < array.size(); k++)
{
std::cout << array[k] << std::endl;
}
}
Reference : wikipidia
That's quite a strange way to implement Selection Sort. You've made several mistakes there, as far as I can see. First of all, you can't use arr.size() in the first for loop, as it would cause the second one to just go off the limits, which causes unexpected behaviour. If by chance those were regular arrays you'd get a nice segmentation fault. Even though you don't get a run-time error, that's something you need to be aware of.
On the other hand, the main problem here is caused by the way in which you are using indexes, as well as the fact that you don't really need a second array.
Here you have an example of this algorithm.
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> array(5);
int aux;
array[0]=10;
array[1]=2;
array[2]=45;
array[3]=-5;
array[4]=0;
for(int i=0; i<array.size()-1; i++)
{
for(int j=i+1; j<array.size(); j++)
{
if(array[j]<array[i])
{
aux=array[j];
array[j]=array[i];
array[i]=aux;
}
}
}
}
Aditionally, I'd recommend you to use vector instead of array, both are STL's containers, but vector is way more flexible and useful, although it consumes some extra memory.
I hope my answer was clarifying enough. I'm here if you need any extra help. Good luck!

Why this code is not showing output for n around 10^5

I have the following code used to calculate primes of the form x^2+ny^2 whihc are not exceeding N. This code runs fine when N is around 80000 but when N is around 10^5 the code breaks down. Why this happens and how to fix this ?
#include <iostream>
#include<iostream>
#include<vector>
const int N = 100000; //Change N in this line
using namespace std;
typedef long long int ll;
bool isprime[N] = {};
bool zprime[N] = {};
vector<int> primes;
vector<int> zprimes;
void calcprime(){
for (int i = 2; i < N; i+=1){isprime[i] = true;}
for (int i = 2; i < N; i+=1){
if (isprime[i]){
primes.push_back(i);
for (int j = 2; i*j < N; j+=1){
isprime[i*j] = false;
}
}
}
}
void zcalc(){
int sqrt = 0; for (int i = 0; i < N; i+=1){if(i*i >= N){break;} sqrt = i;}
for (int i = 0; i <= sqrt; i +=1){
for (int j = 0; j <= sqrt; j+=1){
ll q = (i*i)+(j*j);
if (isprime[q] && !zprime[q] && (q < N)){
zprimes.push_back(q);
zprime[q] = true;
}
}
}
}
int main(){
calcprime();
zcalc();
cout<<zprimes.size();
return 0;
}
Why the code breaks
Out of bounds access. This code breaks because you're doing out of bounds memory accesses on this line here:
if (isprime[q] && !zprime[q] && (q < N)) {
If q is bigger than N, you're accessing memory that technically doesn't belong to you. This invokes undefined behavior, which causes the code to break if N is big enough.
If we change the order so that it checks that q < N before doing the other checks, we don't have this problem:
// Does check first
if((q < N) && isprime[q] && !zprime[q]) {
It's not recommended to have very large c-arrays as global variables. It can cause problems and increase executable size.
(Potentially) very large global arrays. You define isprime and zprime as c-arrays:
bool isprime[N] = {};
bool zprime[N] = {};
This could cause problems down the line for very big values of N, because c-arrays allocate memory statically.
If you change isprime and zprime to be vectors, the program compiles and runs even for values of N greater than ten million. This is because using vector makes the allocation dynamic, and the heap is a better place to store large amounts of data.
std::vector<bool> isprime(N);
std::vector<bool> zprime(N);
Updated code
Here's the fully updated code! I also made i and j to be long long values, so you don't have to worry about integer overflow, and I used the standard library sqrt function to compute the sqrt of N.
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
typedef long long int ll;
constexpr long long N = 10000000; //Change N in this line
std::vector<bool> isprime(N);
std::vector<bool> zprime(N);
vector<int> primes;
vector<int> zprimes;
void calcprime() {
isprime[0] = false;
isprime[1] = false;
for (ll i = 2; i < N; i+=1) {
isprime[i] = true;
}
for (ll i = 2; i < N; i+=1) {
if (isprime[i]) {
primes.push_back(i);
for (ll j = 2; i*j < N; j+=1){
isprime[i*j] = false;
}
}
}
}
void zcalc(){
ll sqrtN = sqrt(N);
for (ll i = 0; i <= sqrtN; i++) {
for (ll j = 0; j <= sqrtN; j++) {
ll q = (i*i)+(j*j);
if ((q < N) && isprime[q] && !zprime[q]) {
zprimes.push_back(q);
zprime[q] = true;
}
}
}
}
int main(){
calcprime();
zcalc();
cout << zprimes.size();
return 0;
}
The value of q can exceed the value of N in your code and can cause a segmentation fault when zprime[q],isprime[q] is accessed. You're iterating i, j till sqrt(N) and have allocated zprime,isprime with N booleans. The value of q can vary from 0 to 2N.
ll q = (i*i)+(j*j);
You can replace bool zprime[N] = {}; and bool isprime[N] = {}; with
bool zprime[N * 2 + 1] = {};
and
bool isprime[N * 2 + 1] = {};
respectively.
The program will no longer segfault. Or, you could check for q < N before accessing isprime[q] and zprime[q].
Also, as has already been pointed out in the comments, (i*i)+(j*j) is an int. It is useless to assign that value to a long long. If you intend to prevent overflow, replace it with ((ll)i*i)+(j*j).
Moreover, for large sized arrays, you should prefer to allocate it on the heap.

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.

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

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;
}