How to initialize a very long array? - c++

I am just trying to initialize a huge array. My code is given below:
#include<iostream>
using namespace std;
int main()
{
int T;
cin >> T;
while (T--)
{
int d;
cin >> d;
int arr[d + 1];
for (int i = 0; i <= d; i++)
arr[i] = 0;
}
return 0;
}
Now when I input
1 502334160
then I got error Runtime Error - SIGSEGV.
I want to know how to initialize this type of array.

The array may be too big to fit in your program's stack address space. If you allocate the array on the heap you should be fine.
int* arr = new int[d + 1];
But remember that this will require you to delete[] the array. A better solution would be to use std::vector<int> and resize it to d + 1 elements.

First: Variable length arrays (VLA) are illegal in C++. It might be an extension (as it is in gcc), but it won't build on all compilers.
Second: You can initialize an array with brace initialization. If you don't specify all elements, the others will get default value of 0 (in case of int). So:
int arr[SIZE] {} //specify 0 elements -> all initialized to value 0
Third thing: you allocate your array on stack, so when you create an array of length 1502334160 than it's stack overflow. This amount of ints (assuming 4 bytes each) is almost 6GB of memory while stack is usually 1-2MB.

Related

Is it dumb to make a dynamic 2d array where the second dimension is a constant?

I am trying to make an array with a variable number of rows, but it will always have 4 columns. Is doing something like:
int** numGrades = new int* [num_exams];
for (int i = 0; i < num_exams; ++i)
{
numGrades[i] = new int[4];
}
a good way to do this? I feel like there's an easier way, but I can't think of one. Also, the array keeps giving me memory leaks so I'm wondering if that is because I'm doing something I shouldn't be. Vectors are banned for this program fyi.
You could make an array of rows.
struct Row{
int values[4];
};
Row* numGrades = new Row[num_exams];
Maybe you can try this.
typedef int row[4];
//or
using row = int[4];
row *numGrades = new row[num_exams];
Allocating some number of arrays of fixed size is fine and advantageous in many cases.
In addition to a struct (which is a very good option), another option is to declare a Pointer-To-Array of a fixed number of elements. The benefit there is you have a Single-Allocation and Single-Free for the block of memory. (as you do with an array of struct) If you need to grow the block of memory (with a -- declare bigger block, copy existing to bigger, delete existing reallocation), it simplifies the process. In your case:
int (*numGrades)[4] = new int[num_exams][4];
Which will allocate num_exams number of arrays of 4 int all at once. That provides the benefit of a single delete[] numGrades; when you are done with the memory.
A short example that uses a std::istringstream to hold example values to be read into a block of memory containing fixes size arrays could be:
#include <iostream>
#include <sstream>
int main (void) {
std::istringstream iss { "1 2 3 4 5 6 7 8 9" };
int npoints = 3,
(*points)[3] = new int[npoints][3],
n = 0;
while (n < 3 && iss >> points[n][0] >> points[n][1] >> points[n][2])
n++;
for (int i = 0; i < n; i++)
std::cout << points[i][0] << " " << points[i][1] << " " << points[i][2] << '\n';
delete[] points;
}
(note: you should avoid using new and delete in favor of a container such as std::vector if this is for other than educational purposes)
Example Use/Output
$ ./bin/newptr2array3
1 2 3
4 5 6
7 8 9
Worth noting, the benefit of the struct is that it will allow you to overload >> and << with std::istream and std::ostream to provide a convenient functions to read and write the data you need.
So either way, a Pointer-to-Array of fixed elements, or creating a struct and then an Array of struct is perfectly fine.
You could skip the for loop:
int* numGrades = new int[num_exams*4];
int firstElement = numGrades[x];
int secondElement = numGrades[x+1];
int thirdElement = numGrades[x+2];
int fourthElement = numGrades[x+3];
By skipping the for loop you gain this:
You don't have to have a for-loop for freeing the memory:
delete[] numGrades;
The heap does not fragment so much because you don't call "new" so many times.
BUT it all depends what you are using it for. In modern C++ is not such a good idea to use dynamic but make a struct in a std::vector.

C++ 2D Array Allocating Memory to Avoid Segmentation Fault

I usually code in other languages (R, Python and Java), but recently started using C++. I've been solving problems on hackerrank.com, and specifically I bumped into this one:
https://www.hackerrank.com/challenges/variable-sized-arrays
Prior to this question, I had never gotten a Segmentation Fault error. I've tinkered with the code and discovered that the error only occurs when I attempt to print from the arr variable.
I wonder if someone could help me with this, and maybe provide a detailed explanation as to the precise error?
The code is as follows, but the issue is likely with int arr[100000][100000] = {-1}; and printf("%d\n", arr[iHat][jHat]); because I can printf both iHat and jHat themselves, but I am unable to use them to access integers in the arr array.
#include <iostream>
using namespace std;
int main(){
int n, q;
/*
*scan in:
*n array entries
*q quaries
*/
int arr[100000][100000] = {-1}; //initialize an array, larger than 10^5
scanf("%d %d\n", &n, &q); //n is size of array, q is # of quaries
for (int i = 0; i < n; ++i){ //loop through lines of input to populate array
int c, y = 0; //initialize to zero at the start of each line
while((c = getchar()) != '\n'){ //readline
if(c != ' '){ //pass spaces
arr[i][y] = c; //place integer into array
++y;
}
}
}
for (int i = 0; i < q; ++i){
int iHat, jHat = 0;
scanf("%d %d\n", &iHat, &jHat); //scan for coordinates
printf("%d\n", arr[iHat][jHat]); //Segmentation fault occurs here, why?
}
return 0;
}
Update
This question focused on memory management, and in particular the use of pointers. A functioning solution, resulting in no segmentation faults, is as follows:
#include <iostream>
using namespace std;
int main(){
int n, q;
/*
*scan in:
*n array entries
*q quaries
* format: %d %d
*/
scanf("%d %d\n", &n, &q);//n is size of array of arrays, q is # of quaries
int **arr = new int *[n]; //int** arr is a pointer of pointers of size n
for (int i = 0; i < n; ++i){//loop through lines of input to populate array
int k; //Always initialize variables in the narrowest scope possible!
scanf("%d", &k);//grab k, the number of ints in the line
arr[i] = new int[k];//create a 2nd dimension at entry i of size k
for (int j = 0; j < k; ++j){
scanf("%d", &arr[i][j]);//populate array
}
}
for (int i = 0; i < q; ++i){
int iHat, jHat = 0;
scanf("%d %d\n", &iHat, &jHat); //scan for query coordinates
printf("%d\n", arr[iHat][jHat]); //print results of query
}
return 0;
}
C++ gives you control of where you want to allocate memory. In your case, what you have found is that you allocated an array-of-array-of-int on the stack which exceeds the stack size. At some point, you access one of these elements which lies outside the bounds of the stack and also the program, which causes an access violation called a segmentation fault.
Since you mentioned being new to C++, it would help to understand these 3 areas of memory and how you would use each for your case:
Stack memory - space for temporary variables to automatically use without having to explicitly request. You will see undefined behavior if you exceed the stack size.
int main() {
int arr[100000][100000];
}
Heap memory - space for dynamically allocating space whenever explicitly requested using the operator "new". An "std::bad_alloc" exception will be thrown if the requested memory size exceeds what is available.
int main() {
int **arr = new int *[100000];
for (std::size_t i = 0; i < 100000; ++i) {
arr[i] = new int[100000];
}
}
Static memory - space allocated for static objects before main runs. You will get a compiler error if the array dimensions are too large.
int arr[100000][100000];
int main() {
...
}
That's 40 GB!
Even if you have that much RAM in the machine, it is surely not allocated as stack space.
If you do have that much memory you can move the arr to the global area before main. That way it will not be on the stack.
If you don't have 40+ GB available, you might have to rethink the solution. :-) Perhaps do the calculations in smaller segments?
Here are a few thoughts
1) You are trying to allocate 100,000 x 100,000 bytes, which equal 10,000,000,000 bytes (~10GB) on the stack. The default stack size is about 8MB on 32-bit linux. Even if the stack size is larger it won't be 10GB.
2) The name of the exercise you were working on is "Variable Sized Array" The line you entered,int arr[100000][100000] is a fixed size array. You should be using keyword new to dynamically create the array.
3) The reason for the Segmentation Fault error is because your print statement is attempting to access memory outside of the Virtual Memory space allowed for a stack size.
[Suggestion]
1) trying doing some exercises where you allocate and clean up dynamic memory using new and delete. Also in C++ allocating and deleting arrays is done differently than just a single data structure.
Cheers
Are you trying to do this?
#include <iostream>
using namespace std;
int main(){
int n, q;
const int length = 100;
int arr[length][length] = { -1 };
cout << "Enter length of 2d array" << endl;
cin>>n>>q;
cout << "Fill the array" << endl;
for (int i = 0; i < n; ++i) {
for(int y=0;y<q;y++){
int f;
cin >> f;
arr[i][y]=f;
}
}
int iHat;
int jHat;
cout << "Enter coordinates" << endl;
cin>>iHat>>jHat;
cout<<arr[iHat][jHat];
return 0;
}
P.S i decreased array size, becouse 100000 x 100000 this is lot of gigabytes and it says array is too large

C++: creating a dynamic array using dynamic memory

I'm trying to create a dynamic array or what should you call that, using pointer, but when I try to cout the length of the array after setting the elements, it gives me 0. I'm not sure what I'm doing wrong here.
Here's the code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int *p = NULL;
int kek = 0;
cin >> kek;
p = new int[kek];
for (int i = 0; i < kek; i++)
{
p[i] = 0;
}
int sizeOfArray = sizeof(p) / 8;
cout << sizeOfArray << endl;
delete[] p;
}
Better use the stl vector, this have the size() method
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> p;
int kek = 0;
cin >> kek;
p.resize(kek);
for (int i = 0; i < kek; i++)
{
p[i] = 0;
}
int sizeOfArray = p.size();
cout << sizeOfArray << endl;
p.clear();
return 0;
}
You are just taking the size of the pointer.
But just use std::vector
You can't use sizeof() to determine the size of a dynamically allocated array because the size can't be determined at compile time, and therefore is not stored anywhere.
When you have a statically allocated array like:
int numbers[40];
The compiler is able to figure out that the size of the block of memory called numbers is 40 items * 8 bytes each = 320 bytes, and determine that a statement like sizeof(numbers) is equivalent to 320, and do the proper substitutions.
But when you have something like
int *numbers = new int[n];
numbers is defined explicitly as a pointer to some memory, and when you do sizeof(numbers), it'll try to evaluate the size of the pointer, which will be 4 or 8 bytes depending on the compiler and platform you're on.
Again, numbers is a pointer, pointing to the first item in a block of memory. There's no easy way to tell which one of the blocks of memory in the computer it's pointing to, and how big the block is in bytes
So that means you'll have to keep track of the size of the array yourself.
You already have the variable kek, so size in bytes should be kek * sizeof(int)
Or like the others have said, you can also use a vector to keep track of the length for you:
vector<int> numbers;
int sizeInBytes = numbers.size() * sizeof(int);
It is not possible to determine the length of a new[]ed array in C++ from a pointer returned by new[]. So, your attempt to "to cout the length" does not really do that. sizeof does not do that and will not help you with that.
The only way to "cout" the size of a new[]ed array is to remember that size and manually carry it from the point where you allocated the array to the point where you need to "cout" the size. If you somehow lose knowledge of that size along the way, you will never be able to restore it.
In your case the size is kek. This is what you "cout".

How to get size of dynamic array in C++ [duplicate]

This question already has answers here:
How to get size c++ dynamic array
(6 answers)
Closed 9 years ago.
Code for dynamic array by entering size and storing it into "n" variable, but I want to get the array length from a template method and not using "n".
int* a = NULL; // Pointer to int, initialize to nothing.
int n; // Size needed for array
cin >> n; // Read in the size
a = new int[n]; // Allocate n ints and save ptr in a.
for (int i=0; i<n; i++) {
a[i] = 0; // Initialize all elements to zero.
}
. . . // Use a as a normal array
delete [] a; // When done, free memory pointed to by a.
a = NULL; // Clear a to prevent using invalid memory reference.
This code is similar, but using a dynamic array:
#include <cstddef>
#include <iostream>
template< typename T, std::size_t N > inline
std::size_t size( T(&)[N] ) { return N ; }
int main()
{
int a[] = { 0, 1, 2, 3, 4, 5, 6 };
const void* b[] = { a, a+1, a+2, a+3 };
std::cout << size(a) << '\t' << size(b) << '\n' ;
}
You can't. The size of an array allocated with new[] is not stored in any way in which it can be accessed. Note that the return type of new [] is not an array - it is a pointer (pointing to the array's first element). So if you need to know a dynamic array's length, you have to store it separately.
Of course, the proper way of doing this is avoiding new[] and using a std::vector instead, which stores the length for you and is exception-safe to boot.
Here is what your code would look like using std::vector instead of new[]:
size_t n; // Size needed for array - size_t is the proper type for that
cin >> n; // Read in the size
std::vector<int> a(n, 0); // Create vector of n elements initialised to 0
. . . // Use a as a normal array
// Its size can be obtained by a.size()
// If you need access to the underlying array (for C APIs, for example), use a.data()
// Note: no need to deallocate anything manually here

reverse c++ array

my aim is to reverse an array 3,12,2,1 to 1,2,12,3. when i run this code i get garbage before my actually result. i can't seem to see where the problem is please assit
#include<iostream>
using namespace std;
int rev (int arr[], int a){
//int r;
for(int i =a-1; i>=0; i--){
cout<<arr[i]<<" ";
}
return 0;
}
int main(){
int arr[] = {6,41,12,5,2};
cout<<"The rev of {6,41,12,5,2}"<<endl;
cout<<rev(arr, sizeof(arr))<<endl;
system("pause");
return 0;
}
Use sizeof(arr)/sizeof(arr[0]) instead of sizeof(arr).
sizeof(arr) gives the total size of the array. sizeof(arr[0]) is the size of one array element (all elements have the same size). So sizeof(arr)/sizeof(arr[0]) is the number of elements.
An optimized answer to the question would be using reverse () from STL if you are allowed to use it:
std::reverse
http://www.sgi.com/tech/stl/reverse.html
int main()
{
int arr[] = {6,41,12,5,2};
cout<<"The rev of {6,41,12,5,2}"<<endl;
reverse(arr, arr + 5);
copy(arr, arr + 5, ostream_iterator<int>(cout, ", "));
}
sizeof return the size in bytes. In your example, if sizeof(int) = 4, it returns 20.
Because you're using an array, you have to keep the size of the array handy as well. sizeof computes the size of a value in memory, in this case the size of all the memory used to represent arr. You can do sizeof(arr)/sizeof(int) to get the number of elements in an array. This makes sense because it's taking the total size of the array and dividing it by the size of an element in the array. Beware however that this only works for arrays (int arr[4] = {6,41,12,5,2};). If it's a pointer to a heap-allocated array via something like int* i = new int[4]; you'll need to keep the size of the array hanging around.
Also, you're calling your reverse function from within a cout<< call, which will print the function's return value (in this case it's hard-coded to 0).
It also turns out there is a function in the C++ standard library (std::reverse) that can do this.
If I may speak subjectively and in an off-topic manner about your approach, it is very un-C-like. My personal favorite way to reverse an array goes like this:
void reverse(int *a, int n)
{
int *p = a, *q = a + n - 1;
while (p < q)
{
int swap = *p;
*p++ = *q;
*q-- = swap;
}
}
// Usage:
int a [] = { /* ... */ };
reverse(a, sizeof(a)/sizeof(*a));
Of course, since your question is tagged c++, there's always std::reverse().
Sizeof operator return the one extra (arrayLength + 1) here 6 will return when passs 6 it store in a when a-1 you get 5 but array index start from 0 length-1 that from 0 to 4 here i pointing to index 5 that is not last element last+1 that why you got garbage value