Segmentation fault on large size array with heap allocation - c++

The following code gives me a segmentation fault when run on a 4Gb machine even after i dynamically allocate the space to the array holding 10 million entries. It works fine with 1 million entries i.e. n = 1000000. The following code sorts integer values along with their index value using radix sort. What should i do to make this program work for 10 million entries.?
int main()
{
int n=10000000; // 10 million entries
int *arr=new int [n]; // declare heap memory for array
int *arri=new int [n]; // declare heap memory for array index
for(int i=0;i<n;i++) // initialize array with random number from 0-100
{
arr[i]=((rand()%100)+0);
}
for(i=0;i<n;i++) // initialize index position for array
{
arri[i]=i;
}
radixsort(arr, n ,arri);
return 0;
}
// The main function to that sorts arr[] of size n using Radix Sort
void radixsort(int *arr, int n,int *arri)
{ int m=99; //getMax(arr,n,arri);
// Find the maximum number to know number of digits
// Do counting sort for every digit. Note that instead
// of passing digit number, exp is passed. exp is 10^i
// where i is current digit number
for (int exp = 1; m/exp > 0; exp *= 10)
countSort(arr, n, exp,arri);
}
void countSort(int *arr, int n, int exp,int *arri)
{
int output[n],output1[n]; // output array
int i, count[10] = {0};
// Store count of occurrences in count[]
for (i = 0; i < n; i++)
{
count[ (arr[i]/exp)%10 ]++;
}
// Change count[i] so that count[i] now contains actual
// position of this digit in output[]
for (i = 1; i < 10; i++)
count[i] += count[i - 1];
// Build the output array
for (i = n - 1; i >= 0; i--)
{
output[count[ (arr[i]/exp)%10 ] - 1] = arr[i];
output1[count[ (arr[i]/exp)%10 ] - 1] = arri[i];
count[ (arr[i]/exp)%10 ]--;
}
// Copy the output array to arr[], so that arr[] now
// contains sorted numbers according to current digit
for (i = 0; i < n; i++)
{
arr[i] = output[i];
arri[i]=output1[i];
}
}

The problem is in countSort. The output and output1 arrays are local arrays, not dynamically allocated, and they're too big for local variables. You're also using the C feature of variable-length arrays, which aren't part of standard C++. Change them to:
int *output = new int[n];
int *output1 = new int[n];
and add
delete[] output;
delete[] output1;
at the end of the function.

Related

Program works fine with small arrays, but it is suspended when the arrays get larger. How to allocate memory to large arrays?

I'll explain my code first before going into my question in more details.
The program will continue to count the next number until the nth number is generated, and then print out that number.
Here's how it works.
With a given sequence of starting numbers, for example, 0,3,6
The 1st number is 0.
The 2nd number is 3.
The 3rd number is 6.
Now, consider the last number, 6. Since that was the first
time the number had been spoken, the 4th number spoken is 0.
(if the last number has been spoken before, then, the next number
is the difference between the turn number when it was last spoken
and the turn number of the time it was most recently spoken before
then. )
since the last number, which is the 4th number (0) has been
spoken before, the most recent place where 0 appears before the last
number is turn 1. Therefore, the 5th number is 4 - 1, which is 3.
...keep counting until the nth number.
My code works fine when n is 2022, but the program stop running when n = 30,000,000
The is how I allocate memory to my arrays
int *test_case_one = new int[30000000];
Below is my entire code
#include <iostream>
#include <string>
using namespace std;
void test_cases( int Array[]);
int isfound( int table[], int current, int range);
int main()
{
int *test_case_one = new int[30000000];
test_case_one[0] = 1;
test_case_one[1] = 3;
test_case_one[2] = 2;
test_cases(test_case_one);
delete[] test_case_one;
}
void test_cases( int Array[])
{
int *table = new int[30000000];
int turn;
int last;
table[0] = Array[0];
table[1] = Array[1];
table[2] = Array[2];
table[3] = 0;
for ( int i = 4; i < 30000000; i++)
{
last = table[i -1];
turn = isfound(table, last, i);
if ( turn != -1) {
table[i] = (i-1) - turn;
}
else {
table[i] = 0;
}
}
cout<< table[29999999] << endl;
delete[] table;
}
int isfound( int table[], int last, int range)
{
for ( int j = range-1; j > 0 ; j--) {
if ( last == table[j -1]) {
return (j - 1);
}
}
return -1;
}
How can I fix this memory overload issue?
You should not build a table of the values, but a table of last rank per value, initialized to 0. That way when you get a value, you have a direct access to next value and you algo become simply linear.
If you are sure that none of the initialization values will be greater than the expected number of iterations, then everything is fine because as other values will be index differences, this will also be less than that number.
Here is a simple code for your 0-3-6 example:
#include <iostream>
int main()
{
int number;
std::cout << "Total number (>=7): ";
std::cin >> number;
if (!std::cin || number < 5) return EXIT_FAILURE;
// 3 initial values are 0, 3, 6, so 4th will be 0
int* data = new int[number];
for (int i = 0; i < number; i++) data[i] = 0;
data[0] = 1;
data[3] = 2;
int val = 6;
for (int index = 3; index <= number; index++) {
int newval = data[val] ? index - data[val] : 0;
data[val] = index;
val = newval;
// uncomment next line to see intermediary values
//printf("%d: %d\n", index + 1, val);
}
delete[] data; // always release dynamic objects...
printf("Final %d: %d\n", number, val);
return 0;
}
BTW, in modern C++ you should rarely directly allocate a raw array with new, precisely because if you do, you will be responsible for its deletion. It is much more common and easy to use standard containers, here a std::vector. (Thanks to #EtiennedeMartel for the remark).

Deleting elemnt from array and calculating sum

Number can't be in array if it can be divided by number of elements of array (for example: in array which has 10 elements, numbers 1,2,5 and 10 are not "welcome"). So I need to find all these elements in array and kick them out. After that length of array changes, and then some other elements can be "not welcome" in array. I have to repeat it until array is without these elements. In the end, I have to calculate remaining elements and print them out. (I'm using C++)
I didn't know how to delete element from array, and just set value to 0.
I get input n (number of elements in array) and then all of these elements.
So, I already tried it but I'm sure there is much more effective way to do it :P Here is the code:
int main()
{
short int b = 0;
short int n;
int result = 0;
cin >> n;
int m = n;
int numbers[n];
for (int i = 0; i < n; i++) {
cin >> numbers[i];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j<=n; j++) {
if(numbers[j] != 0) {
if(n % numbers[j] == 0) {
numbers[j] = 0;
b = b + 1;
} }
}
n = n - b;
b = 0;
}
for (int i = 0; i < m; i++) {
result += numbers[i];
}
cout << result;
return 0;
}
example input: 10 1 2 3 4 5 6 7 8 9 10
example output: 24
I didn't know how to delete element from array
It is not possible to "delete element from array". An array of n elements begins its life with n elements, has n elements throughout its entire lifetime, and ends its life with n elements. It is not possible to change the size of an array.
Another problem:
cin >> n;
int numbers[n];
The size of an array must be a compile time constant. n is not a compile time constant. This is not a well-formed C++ program.
An array of runtime size must be allocated dynamically. The easiest solution is to use std::vector. The size of a vector can change, and you can use std::vector::erase to remove elements from it.

How to find all possible combinations of 5 numbers in an array 0-9

I am new to C++ programming and I would like to get all the possible combinations of a one-dimensional array with 5 elements and without numbers repeating for example it starts with 00001, 00002, 00003, ... ,99999.
int count(){
while (i<100000){ //loop to go thru all possible combinations
//std::cout<<i<<"\t";
if (i>=10000){
num(i);
print();
}
i++;
}
}
void num (int i){ /* method to sort all the number to the array for i */
takeNumbersFromUser=i;
for( n=0;n<arraySize;n++){
if (control==0){
ar[n]=takeNumbersFromUser % 10;
}
else if (control==1){
temp= takeNumbersFromUser % 100;
ar[n]=temp/10;
}
else if (control==2){
temp = takeNumbersFromUser % 1000;
ar[n] = temp/100;
}
else if (control==3){
temp = takeNumbersFromUser % 10000;
ar[n] = temp/1000;
}
else if (control==4){
temp = takeNumbersFromUser % 100000;
ar[n] = temp/10000;
}
control++;
}
}
void print(){ //print out
std::cout<<"\n\n\tyou entered "<<takeNumbersFromUser<<"\n\n";
for (n=5;n>=0;n--){
std::cout<<ar[n]<<"\t";
}
}
}
Thank you.
Something like?
// Size of parent array (10^length)
int size = 100000;
// Length of number
int length = 5;
// Two dimensional array to hold the numbers
int** matrix = new int*[size];
// Create all elements in the array
for(int i=0;i<size;i++) {
matrix[i] = new int[length];
// Temporary variable to "play" with 'i'
int temp = i;
for(int j=length-1;j>=0;j--) {
matrix[i][j] = temp%10;
temp /= 10;
}
}
I believe this is very simple, and does not require further explanation.
If it does, please ask and I will provide
EDIT:
As suggested, you can replace the int* array with:
new vector<int>[size]
Then in the for j loop, there is no need to create a new array, and you can just use: matrix[i].push_back(temp%10)
And finally, to print this, you can do a new for i loop, going over the vectors array, and inside to have a foreach loop, something like:
for(int n : v)
std::cout << n << " ";
You can deffinetly should be able to manage from here.

I'm trying to sort an array by counting the elements and then sort them again "counting sort"

I'm trying to sort the array by making another array with size of the maximum number in the array I want to sort, then each time I find the number I ++ the index of that number..ex: the main array is {5,3,8,1,2,3}
the other array {0,1,1,2,0,1,0,0,1}
then my sorted array will be like {1,2,3,3,5,8} I have no idea why my code is not working any help please?
#include <iostream>
using namespace std;
int findmax(int a[], int size){
int max = a[0];
for (int i = 0; i < size; i++)
if (max < a[i])
max = a[i];
return max;
}
void sort(int a[], int n){
int max = findmax(a, n);
int *arr;
arr = new int[max+1];
for (int i = 0; i < n; i++){
arr[a[i]]++;
}
for (int k = 0; k < n;){
for (int l = 0; l <= max; l++) {
while (arr[l] != 0){
a[k] = l;
arr[l]--;
k++;
}
}
}
What you really should be doing is to step through the code line by line in a debugger. That way you will easily see what the problem is.
But since I started writing this I might as well post it as an answer.
The problem is that the array you allocate and assign to arr is not initialized, its contents is indeterminate. And using uninitialized data is undefined behavior.
What's really is happening is that the data you allocate will be seemingly random, and most likely none of it will be zero. That leads to your counts being all wrong.
The solution is to clear the memory you allocate before counting values:
std::fill(arr, arr + max + 1, 0);

Implementing the insert array method for a hand-written dynamic array - C++

So my code is supposed to take a dynamic array and inserts a smaller array into it and if there's not enough space in the larger array then it makes a new array and copies the values from the old array into the new one so that the smaller array can be inserted. Here's the code that allocates the new size for the new array with dynamic_array &a being the smaller array and i being the position it's inserted to:
void dynamic_array::insert(dynamic_array &a, int i) {
if (i < 0 or i > size){
throw exception(SUBSCRIPT_RANGE_EXCEPTION);
}
int *new_array;
int range = a.get_size(); //my get size method will return how many values are in a
int blocks_needed = (size) / BLOCK_SIZE;
if (size % 5 > 0) {
blocks_needed = blocks_needed + 1; //add a block if needed
}
if (size + range >= allocated_size) { //new space needed
//get more space
try {
new_array = new int[blocks_needed * BLOCK_SIZE];
} catch (bad_alloc){
throw exception (MEMORY_EXCEPTION);
}
Then there's 3 different for loops. One copies all the elements before i-1. The second copies all the elements in array a. The third one copies all the remaining elements from the old array into the new array while shifting them over:
//copy array[0..i-1]
for (int j = 0; j < i; j++) {
new_array[j] = array[j];
}
//copy a
for (int m = i; m < range; m++){
new_array[m] = a[m];
}
//copy array[i..size-1]
for (int k = i; k < size; k++) {
new_array[k+range] = array[k];
}
Afterwards I update the sizes:
size = size + range;
allocated_size = blocks_needed * BLOCK_SIZE;
Now if there is already enough space then I just shift the array to the right and insert the values via a for loop:
else { //no new space needed
shift_right(i, size, range);
for (int z = i; z < range; z++){
array[z] = a[z];
}
size = size + range;
}
Now the output I'm getting is quite close to what I want however it's not quite what I want. There's alot of times where the array values show things like 0 3 0 2 4 when it should show 0 1 3 2 4. The allocated size is also sometimes wrong when it shows that it's 5 when it should be 10. The size looks fine for all tested arrays but it's just the allocated size and the array values that's the problem. Here's my shift right function:
void dynamic_array::shift_right(int start, int end, int delta){
for(int i=end; i>=start; i--){
array[i+delta] = array[i];
}
return;
}
Alright so while we don't have all the code for the method being discussed, nor the dynamic_array::shift_right() code, I've noticed two mistakes right off the bat (thanks to #TheDark for nitpicking on my fix):
First one:
for (int m = i; m < range; m++) { new_array[m] = a[m]; }
Should be
for (int m = i; m < range + i; m++) { new_array[m] = a[m - i]; }
// ^^^ ^^^
Another one of the same kind in the last, shifting loop:
for (int z = i; z < range; z++) { array[z] = a[z]; }
Should be:
for (int z = i; z < range + i; z++) { array[z] = a[z - i]; }
// ^^^ ^^^
In fact, these may be causing a crash on trying to access a[] out of bounds. On a side note, that's one of the reasons why it's better, namely safer, to use iterators than simple integer indices for container access.
I didn't like this either:
int blocks_needed = (size) / BLOCK_SIZE;
if (size % 5 > 0) {
blocks_needed = blocks_needed + 1; //add a block if needed
}
This looks very much like hand-writing the ceil() function. Other than that, 5 apparently should equal BLOCK_SIZE, else this makes little sense to me. Thus, replace 5 with BLOCK_SIZE or better yet switch to ceil().
Now on to the allocation-related errors. Here's one:
int blocks_needed = (size) / BLOCK_SIZE;
int blocks_needed = (size + range) / BLOCK_SIZE;
// ^^^^^^^
And here's another, while not really an error, but it's suboptimal behavior nonetheless:
if (size + range >= allocated_size) { //new space needed
if (size + range > allocated_size) { //new space needed
// ^^^