Hey everyone I am relearning C++ by doing some hacker rank challenges and am getting a segment fault error. The program should take in the dimensions for the matrix and compute both diagonals, then add them together. I am pretty sure the error is in how the 2d array is passed to the computeMainDiagonal and computeSecondaryDiagonal functions. Thanks for the help !
int ComputeMatrixMainDiagonal(int matrixDimensions, int* matrix){
int rowIndent = 0;
int diagonalValue;
for(int i = 0;i < matrixDimensions;i++){
diagonalValue =+ (&matrix)[i][rowIndent];
rowIndent++;
}
return diagonalValue;
}
int ComputeMatrixSecondaryDiagonal(int matrixDimensions, int* matrix){
int rowIndent = matrixDimensions;
int diagonalValue;
for(int i = matrixDimensions;i > 0;i--){
diagonalValue =+ (&matrix)[i][rowIndent];
rowIndent--;
}
return diagonalValue;
}
int main() {
int matrixDimension;
int differenceAcrossSumsOfDiagonal;
int matrixMainDiagonal;
int matrixSecondaryDiagonal;
int * matrixPointer;
cin >> matrixDimension; //get matrix dimensions
int matrix[matrixDimension][matrixDimension]; //declare new matrix
for(int index = 0; index < matrixDimension;index++ ){ //populate matrix
for(int i = 0; i < matrixDimension;i++){
cin >> matrix[index][i];
}
}
matrixMainDiagonal = ComputeMatrixMainDiagonal(matrixDimension,&matrix[matrixDimension][matrixDimension]);
matrixSecondaryDiagonal = ComputeMatrixSecondaryDiagonal(matrixDimension,&matrix[matrixDimension][matrixDimension]);
differenceAcrossSumsOfDiagonal = (matrixMainDiagonal + matrixSecondaryDiagonal);
cout << differenceAcrossSumsOfDiagonal;
return 0;
}
Your segmentation fault likely occurs because &matrix[matrixDimension][matrixDimension] does not mean what you think it means. Your question title suggests that you think this is a way to pass the array by value (though why you would want to do so escapes me), but pass-by-value vs. pass-by-reference is a matter of how the function is declared, not of how it is called.
The expression &matrix[matrixDimension][matrixDimension] would be the address of the matrixDimensionth element of the matrixDimensionth row of the matrix. This is outside the bounds of the matrix, as the maximum index for an array is one less than the array dimension. Even if you wrote &matrix[matrixDimension - 1][matrixDimension - 1], however, it would not be what you want. You want the address of the first element of the array, which is &matrix[0][0] or simply matrix, though these are inequivalent on account of having different type (corresponding to different senses of what the elements of matrix are).
Related
I would like to determine if there is a way to determine whether a dynamically allocated matrix is square (nxn).
The first thing that came to mind was to see if there is a way to find out whether a pointer is about to point to an invalid memory location. But according to these posts:
C++ Is it possible to determine whether a pointer points to a valid object?
Testing pointers for validity (C/C++)
This cannot be done.
The next idea I came up with was to somehow use the sizeof() function to find a pattern with square matrices, but using sizeof() on a pointer will always yield the same value.
I start off by creating a dynamically allocated array to be of size nxn:
int **array = new int*[n]
for(int i = 0; i < n; i++)
array[i] = new int[n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
array[i][j] = 0;
}
}
Now I have a populated square matrix of size nxn. Let's say I'm implementing a function to print a square 2D array, but a user has inadvertently created and passed a 2D array of size mxn into my function (accomplished by the code above, except there are more row pointers than elements that comprise the columns, or vice versa), and we're also not sure whether the user has passed a value of n corresponding to n rows or n columns:
bool(int **arr, int n){
for(int rows = 0; rows < n; rows++)
for(int cols = 0; cols < n; cols++)
cout << *(*(arr + rows) + cols) << " ";
// Is our next column value encroaching on unallocated memory?
}
cout << endl;
// Is our next row value out of bounds?
}
}
Is there any way to inform this user (before exiting with a segmentation fault), that this function is for printing square 2D arrays only?
Edit: corrected 3rd line from
array[i] = new int[i]
to
array[i] = new int[n]
There is NO way to find out information about an allocation. The ONLY way you can do that, is to store the information about the matrix dimensions somewhere. Pointers are just pointers. Nothing more, nothing less. If you need something more than a pointer, you'll need to define a type that encapsulates all of that information.
class Matrix2D
{
public:
Matrix2D(int N, int M)
: m_N(N), m_M(M), m_data(new int[N*M]) {}
int N() const { return this->m_N; }
int M() const { return this->m_M; }
int* operator[] (int index) const
{ return m_data + m_M * index; }
private:
int m_N;
int m_M;
int* m_data;
};
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
I am quite new to programming,so I really need help. I need to wrtie a function which produce 2d arrays with random values. here is my code:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
float randArray(int row, int column);
int main()
{
int r = 10, c = 8;
float fckMmd = randArray(r,c);
///printing the array:
for (int row=0; row<r; row++){
for (int column=0; column<c; column++){
cout << fckMmd[row][column] << " ";
}
cout << endl;
}
}
float randArray(int row, int column){
srand(time(NULL));
float *randArr;
randArr = new int [row][column];
for(int k=0; k<row; k++){
for(int kk=0; kk<column; kk++){
randArr[k][kk] = rand();
}
}
return randArr;
}
But I get the error mentioned above. Where is the problem? help me please
randArr is a float * but you try to allocate a 2d array in it. A 2d array is not the same thing as a pointer. Your function only returns 1 float as well. I suggest you use vectors (also so you don't leak memory). Furthermore you should only call srand ONCE, not every time, and be aware rand() returns an integer, not a floating point value.
std::vector<std::vector<float>> randArray(int row, int column)
{
std::vector<std::vector<float>> randArr(row);
for (auto& v : randArr)
{
v.resize(column);
}
for(int k=0; k<row; k++)
{
for(int kk=0; kk<column; kk++)
{
randArr[k][kk] = static_cast<float>(rand());
}
}
return randArr;
}
It's because fckMmd is only a float and not a pointer or array.
First:
float *randArr;
declares a pointer to float. You then do
randArr = new int [row][column];
which allocates memory for a 2D array of ints (incompatible types, technically you allocate memory for a pointer to arrays of type int[column]), hence the error.
You're better using a std::vector instead, or, if you want a manually-managed dynamically allocated 2D array, use float **randArr; instead, and allocate
float** randArr;
randArr = new float* [rows];
for(int i = 0; i < row; ++i)
randArr[i] = new float[col];
or
float (*randArr)[col]; // pointer to array float[col]
randArr = new float[row][col];
Other issues: most of the time, srand must be used only once in the program. It is a good idea to call it in main() and not bury it into a function, since you may end up calling the function multiple times.
Last issue: if you want speed, you're better off using a single flat array (or std::vector) and map from 2D to 1D and vice versa, since your data will be guaranteed to be contiguous and you'll have very few cache misses.
So I have looked through some online questions to figure out how to setup and fill a dynamic multidimensional array and I thought I had it down but for some reason my function will not access the anything past the first(0) column. For my test I put in a 2X2 array:
2 2 (part of another function that gives the size of the matrix)
1 2
3 4
When I debug it I only get
1 random# from initializing the array
3 random# from initializing the array
I'm not sure what I am doing wrong with this piece of code, I am also new to C++.
double* matrix_read(const int m, const int n)
{
double **mat = new double*[m];
for (int j = 0; j < m; ++j) {
mat[j] = new double[n];
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
cin >> mat[i][j];
}
}
double debug = mat[2][2];
return *mat;
}
Inside the main function this is what I send to the function.
int x, y, m, n;
cin >> x;
cin >> y;
double *mat_a = matrix_read(x, y);
cin >> m; //2nd matrix read in
cin >> n;
double *mat_b = matrix_read(m, n);
Your matrix is represented as an array of pointers, each pointer in the array points, in turn, to an array of doubles. Each of these arrays are contiguous in memory, but not among themselves. This means that, mat[0][0] is right before mat[0][1] in memory. But mat[1][0] may be in a completely different location.
By returning only the first line of your matrix, *mat (the same as mat[0]), you will lose information. All you have access to is the first line.
You should return the whole matrix.
double** matrix_read(...) {
...
return mat;
}
(Edit: Besides, someone will have to delete the matrix later.. and they have to delete several arrays, ugh. You should make a structure wrapper for matrices, or use a single array, or use a vector of vectors)
I have a problem with two dimensional arrays :( I feel very stupid and Visual C does not help me :( and I also think that my mistake is very stupid but still I can't find it :( I have this code:
double matrix[100][100]; //which is full with a matrix 3x4
double nVector[10000]; // for negative doubles
//I wanted to see if there are negative doubles in each row and column
//and I want this to happen with function
And this is my function:
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*(*(myMatrix+i)) < 0){
*(myNegArray+position) = *(*(myMatrix+i));
position++;
}
return myNegArray;
}
//for double*nVector I'm passing nVector
//for double*fromVector I'm passing *matrix
Visual C tells me that I have an error C2100: illegal indirection here: *(*(myMatrix+i)) I hope someone can help me (happy)
Thanks in advance!
*(*(myMatrix+i)) is wrong. This is a common mistake.
2D matrix does not create an array of pointers which you can access this way. It is a different structure. Even though an array is a pointer, 2D array is not a pointer to pointer, and it cannot be dereferrenced twice. Nor you have any other way to access element at coordinates (x,y) without knowing the layout in memory, because pointers to every line are nowhere to be found. For instance, char **argv parameter of main() is not a 2D array. This is an array of pointers to arrays, which is something else.
There're two ways to fix it.
One is replace
double *myMatrix = fromVector;
by
double *myMatrix[100] = (appropriate cast)fromVector;
and index it as myMatrix[i/n][i%n]
But then remember that 100 is a constant expression, and it cannot be passed as a parameter. Alternatively, you can implement the indexing operation yourself:
Pass additional parameter: matrix line size (100)
Instead of *(*(myMatrix+i)), write:
int row = i/n;
int col = i%n;
*(myMatrix+row*line_size+col) is your element.
first you might wanna start a small struct like
struct tmp {
bool negative;
double value;
};
and make your own way up to the
tmp *myvars [100][100];
.
instead try using that struct and try the std::vectors instead of arrays if that's possible then try using pointers on decalring the variable "1 time only" when declaring the variable as i said above
then pass arguments
( tmp *mystructpointer )
mystructpointer->.......
access your matrix directly ... peice of cake :D
If you are passing *matrix, you are actually passing a double[100] (an array of 100 doubles), that happens to be passed as a pointer to its first element. If you advance further than those 100 doubles using i added to that pointer, you advance into the next array of 100 doubles, since the 100 arrays of 100 doubles are stored next to each other.
Background: A multi-dimensional array is an array whose element type is itself an array. An array like double a[100][100]; can be declared equivalently as typedef double aT[100]; aT a[100];. If you use an array like a pointer, a temporary pointer is created to the array's first element (which might be an array). The * operator is such an operation, and doing *a creates a pointer of type double(*)[100] (which is a pointer to an array of 100 doubles), and dereferences it. So what you end up with *matrix is a double[100]. Passing it to the negativeVector function will create a pointer to its first element, which is of type double*.
Your pointer parameters point to the start of each of two arrays of 100 doubles each. So you should rewrite the function as
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*(myMatrix + i) < 0){
*(myNegArray + position) = *(myMatrix + i);
position++;
}
return myNegArray;
}
Notice that since your i iterates beyond the first of the 100 arrays stored in the 2d array, you will formally not be correct with this. But as it happens those arrays must be allocated next to each other, it will work in practice (and in fact, is recommended as a good enough work around for passing multi-dimensional arrays around as pointers to their first scalar element).
I have no clue why you are copying the arrays twice (once in the parameters of the function and a second time by declaring some new arrays)... You should also think of using the STL... std::vector will make the your life way easier ;)
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*((myMatrix+i)) < 0){
*(myNegArray+position) = *((myMatrix+i));
position++;
}
return myNegArray;
}
is that homework? some templates - just for fun ;-)
double matrix[100][100];
double nVector[10000];
template< const int m, const int n >
double* negativeVector( double* myNegArray, const double (&myMatrix)[m][n] )
{
int position = 0;
for( int i = 0; i < m; ++i )
{
for( int j = 0; j < n; ++j )
{
const double value = myMatrix[ i ][ j ];
if ( value < 0 )
{
myNegArray[ position ] = value;
++position;
}
}
}
return myNegArray;
}
int main()
{
//...initialize matrix here...
negativeVector( nVector, matrix );
}
Perhaps rewrite this using std::vector to increase readability? (#):
#include <vector>
std::vector< std::vector<double> > matrix; //which is full with a matrix 3x4
std::vector<double> row;
row.resize(100,0);
matrix.resize(100,row);
std::vector<double> nVector; // for negative doubles, no size, we'll "push_back"
//I wanted to see if there are negative doubles in each row and column
//and I want this to happen with function
This is the stl enabled version of the function:
//I'm returning void because nvector contains the result,
//so I don't feel the need to return anything. vectors contain their
//own size so n and m are also not needed. Alsom pass in references
void negativeVector(std::vector<double>& nVector,
std::vector< std::vector<double> >& fromVector){
nVector.clear();
int i,j;
for(i = 0; i < fromVector.size(); i++) {
for(j = 0; j < fromVector[i].size(); j++) {
if(fromVector[i][j] < 0){
nVector.push_back(fromVector[i][j]);
}
}
}
}
call with:
negativeVector(nVector, matrix);
Once the function completes, nVector contains all negative numbers in matrix.
Read more about std::vector here.
(#) for people like me who are too lazy/stupid to comprehend code containing pointers.
Take a look at C++ Faq site:
How do I allocate multidimensional arrays using new?
link
And read until point [16.20] summarize all the answers you are getting and at the end you get a very useful Matrix template class.
Have a good read.