I dunno why I have segmentation error when I'm trying to set or get any element from created array!!
Here it is in line with A[0][0] = 1;
I'm using g++ 9.3.0. What do I do wrong?
#include <iostream>
#define SIMULATIONS 30
using namespace std;
void init_matrixes(int a_rows, int b_cols, int vec_len, double **A, double **B, double **C)
{
A = new double *[a_rows];
B = new double *[vec_len];
C = new double *[a_rows];
for (int i = 0; i < a_rows; i++)
{
A[i] = new double[vec_len];
C[i] = new double[b_cols];
}
for (int i = 0; i < vec_len; i++)
B[i] = new double[b_cols];
}
int main()
{
double s;
int t1, t2, a_rows, b_cols, vec_len;
for (auto v : {50, 100})
{
a_rows = v;
b_cols = v;
vec_len = v;
for (int i = 0; i < SIMULATIONS; i++)
{
double **A, **B, **C;
init_matrixes(a_rows, b_cols, vec_len, A, B, C);
A[0][0] = 1; // error here
}
std::cout << "size = " << v<< " time = " << s / SIMULATIONS << endl;
}
return 0;
}
TL;DR version
Use std::vector or a matrix class like the one described here. This will eliminate the need for special allocation and deallocation functions thanks to the magic of RAII.
What went wrong?
A pointer is just another variable, but one that can contain the location of another object. Like any other variable, the pointer will be will be passed by value into a function and copied by default. The object pointed at is passed by reference (by way of pointer), but the pointer itself is passed by value.
double **A defines A as a pointer to a pointer to a double that is a copy of the pointer provided by the caller.
A = new double *[a_rows];
updates the copy and the caller is none-the-wiser. As a result all of the memory allocated is leaked at the end of the function because the local A goes out of scope.
So How do I fix it?
Pass the pointers by reference.
void init_matrixes(int a_rows,
int b_cols,
int vec_len,
double ** & A,
double ** & B,
double ** & C)
A, B, and C, are passed by reference (references this time) and are no longer copies.
A = new double *[a_rows];
Updates the pointer provided by the caller, and the caller now has a pointer pointing to valid storage.
Related
In my code I create a function outside of the main, which creates a 1D array and initializes to 0.
void create_grid(double *&y, int Npoints)
{
y = new double[Npoints];
for (int i = 0; i < Npoints; i++)
{
y[i] = 0;
}
}
If I didn't have the syntax of declaring in the function as double *&y I couldn't access the values of y.
I tried doing the same for a 2D array but i don't know the syntax. I tried &&**y and &*&*y but it didn't work. Does anyone know how to create a function outside of the main, which initializes a 2d dynamic array so I can use it in the main?
E.g.:
void create_grid_2D(double **&&y, int Npoints1, int Npoints2)
{
y = new double*[Npoints1];
for (int i = 0; i < Npoints1; i++)
{
y[i] = new double[Npoints2];
}
for (int i = 0; i < Npoints1; i++)
{
for (int j = 0; j < Npoints2; j++)
{
y[i][j] = 0;
}
}
}
int main()
{
int N = 10;
double **z;//correcting this line, i wrote z**
create_grid_2D(z, N, N);
delete[]z;
return 0;
}
C++ does not allow forming a pointer to reference or reference to reference. (And without a space between the characters, && is a single token meaning something entirely different.)
And your declaration double z**; is incorrect - you probably mean double **z;.
To write a function that takes the argument double **z by reference, you just want a reference to pointer to pointer:
void create_grid_2D(double **&y,int Npoints1,int Npoints2)
{
//...
}
Except don't use new and delete. Using them slightly wrong leads to memory leaks and bugs with dangling pointers and double deletes. For example, you tried to clean up your memory in main with delete []z;, but new-expressions were evaluated 11 times to your one delete-expression, so this misses out on deleting the row arrays z[0], z[1], ... z[9]. There's pretty much always a better and simpler way using std::unique_ptr, std::shared_ptr, std::vector, or other RAII (Resource Allocation Is Initialization) tools.
So I would change the function to:
void create_grid_2D(std::vector<std::vector<double>>& y,
unsigned int Npoints1,
unsigned int Npoints2)
{
y.assign(Npoints1, std::vector<double>(Npoints2, 0.0));
}
int main()
{
unsigned int N=10;
std::vector<std::vector<double>> z;
create_grid_2D(z, N, N);
// No manual cleanup necessary.
}
Or even use a return value rather than assigning an argument:
std::vector<std::vector<double>> create_grid_2D(
unsigned int Npoints1,
unsigned int Npoints2)
{
return std::vector<std::vector<double>>(
Npoints1, std::vector<double>(Npoints2, 0.0));
}
int main()
{
unsigned int N=10;
std::vector<std::vector<double>> z = create_grid_2D(N, N);
}
An easy trick to resolve/write such complicated references is (simplified version for the sake of this problem - it's a bit more complicated with braces present): start from the variable name and go to the left, step by step. In your case:
... y
y is ...
... & y
y is a reference ...
... *& y
y is a reference to a pointer ...
... **& y
y is a reference to a pointer to a pointer ...
double**& y
y is a reference to a pointer to a pointer to a double
So, the correct definition is:
void create_grid_2D(double**& y,int Npoints1,int Npoints2)
But as mentioned in the comments, please do really consider avoiding raw pointers in favor of std::vector and other standard containers.
So you want a reference on a pointer to a pointer.
2d pointer is int**, and the reference is int**&. That's what you want to use.
Then, you should a container or at least a smart pointer instead.
This approach would be a little different than what you currently have but basically you want a 2D grid and another name for this is simply a MxN Matrix! We can do this very easily with a simple template structure. This template class will hold all of the contents without having to put the data into dynamic memory directly. Then once you have your class object that you want to use we can then put that into dynamic memory with the use of smart pointers!
#include <iostream>
#include <memory>
template<class T, unsigned M, unsigned N>
class Matrix {
static const unsigned Row = M;
static const unsigned Col = N;
static const unsigned Size = Row * Col;
T data[Size] = {};
public:
Matrix() {};
Matrix( const T* dataIn ) {
fillMatrix( dataIn );
}
void fillMatrix( const T* dataIn );
void printMatrix() const;
};
template<class T, unsigned M, unsigned N>
void Matrix<T, M, N>::fillMatrix( const T* dataIn ) {
for ( unsigned i = 0; i < Size; i++ ) {
this->data[i] = dataIn[i];
}
}
template<class T, unsigned M, unsigned N>
void Matrix<T,M,N>::printMatrix() {
for ( unsigned i = 0; i < Row; i++ ) {
for ( unsigned j = 0; j < Col; j++ ) {
std::cout << this->data[i*Col + j] << " ";
}
std::cout << '\n';
}
}
int main() {
// our 1 day array of data
double data[6] = { 1,2,3,4,5,6 };
// create and print a MxN matrix - in memory still a 1 day array but represented as 2D array
Matrix<double,2,3> A;
A.fillMatrix( data );
A.printMatrix();
std::cout << '\n';
Matrix<double, 3,2> B( data );
B.printMatrix();
std::cout << '\n';
// Want this in dynamic memory? With shared_ptr the memory is handled for you
// and is cleaned up upon it's destruction. This helps to eliminate memory leaks
// and dangling pointers.
std::shared_ptr<Matrix<float,2,3>> pMatrix( new Matrix<float,2,3>( data ) );
pMatrix->printMatrix();
return 0;
}
Output:
1 2 3
4 5 6
1 2
3 4
5 6
1 2 3
4 5 6
I'm converting C++ code to C for an exercise (we are just learning c++ now), and I am lost at this part.
First, the c++ code:
Point()
{
x = y = 0;
}
main()
{
const int N = 200;
Point *A = new Point[N], sum;
}
Here's my C version of it:
struct Point //constructor
{
int x;
int y;
} Point;
main()
{
int N = 200;
Point* A = malloc(N * sizeof(*Point[]));
}
That should give you an idea of what I'm trying to do. Questions:
Is sum in the C++ code the C++ sum function, or is it aPointstruct`?
For allocating the memory in C, I don't think my method works. Should I do a for loop where it mallocs each index of A[]? (A should be an array of Point structs).
Any assistance would be greatly appreciated.
EDIT: Got asked for the context of the code.
Here's the whole C++ program:
#include <iostream>
// a point on the integer grid
struct Point
{
// constructor
Point()
{
x = y = 0;
}
// add point componentwise
void add(const Point &p)
{
x += p.x;
y += p.y;
}
// print to standard output
void print() const
{
std::cout << "[" << x << "," << y << "]" << std::endl;
}
// data
int x, y;
};
int main()
{
const int N = 200;
Point *A = new Point[N], sum;
for (int i=0; i < N; ++i) {
sum.print();
A[i].x = i; A[i].y = -i;
sum.add(A[i]);
}
sum.print();
delete [] A;
}
Ultimately, I have to emulate that in C. Currently stuck at the question I asked: re: what does that line do. I have since figured out that I need to make a struct of Point called sum, and print that after running the add function on all its members.
In your C version:
struct Point //constructor
{
int x;
int y;
} Point;
should be:
typedef struct //constructor
{
int x;
int y;
} Point;
Because in your case, you defined a global variable named Point.
And, the C programming language has the const keyword as C++ as well, so you can do this in the C language:
const int N = 200;
And the C++ code:
Point *A = new Point[N], sum;
In C version, should be:
Point *A = malloc(N * sizeof(Point)), sum;
But in this version, the memory isn't initialized by zero.
You can use the calloc function instead of the malloc to allocate memory and initialize it with zero:
Point *A = calloc(N, sizeof(Point)), sum;
Then back to your question:
Is sum in the c++ code the c++ sum function, or is it a Point struct?
It is a Point type variable.
For allocating the memory in C, I don't think my method works. Should I do a for loop where it mallocs each index of A[]? (A should be an array of Point structs).
No, there's no necessary to write a for loop. The malloc function will do exactly what you want.
Is sum in the c++ code the c++ sum function, or is it a Point struct?
In your case, it is a Point struct.
Point *A = new Point[N], sum;
is equivalent to:
Point *A = new Point[N];
Point sum; //I have no idea why naming is sum
If you need Point* for sum, you should write it in the following way:
Point *A = new Point[N], *sum;
For allocating the memory in C, I don't think my method works
It does not work, syntax is wrong. Try:
EDIT: thanks to #mch, you should not use cast for malloc.
typedef struct Point Point;
Point* A = malloc(N * sizeof(Point));
I keep getting the error message, exc_bad_access code=1 for my line
asize = *(***(y) + **(y + 1));
in the summation function. I dont quite understand what to do with this error, but i know that it is not a memory leak.
I am trying to get the values stored in the y pointer array, add them, and store it in the variable asize.
void allocArr (int **&x, int ***&y, int **&q, int ****&z)
{
x = new int *[2];
y = new int **(&*x);
q = &*x;
z = new int ***(&q);
}
void putArr(int **&x, int &size1, int &size2)
{
*(x) = *new int* [size1];
*(x + 1) = *new int* [size2];
}
void Input (int **&x, int *&arr, int &size1,int &size2, int a, int b)
{
cout << "Please enter 2 non-negative integer values: "<< endl;
checkVal(size1, a);
checkVal(size2, b);
putArr(x, size1, size2);
arr[0] = size1;
arr[1] = size2;
cout << x[0];
}
void summation(int ***&y, int *&arr)
{
int asize = 0;
asize = *(***(y) + **(y + 1));
**y[2] = *new int [asize];
*(arr + 2) = asize;
}
int main()
{
int size1, size2;
int a = 1, b = 2;
int** x;
int*** y;
int** q;
int**** z;
int *arr = new int [2];
allocArr(x, y, q, z);
Input(x, arr, size1, size2, a, b);
summation(y, arr);
display(z);
}
Thank you for the help. Im really struggling here...
Not sure how you got started with the code. The code can be simplified quite a bit to help you, and readers of your code, understand what's going on.
Function allocArr
The lines
y = new int **(&*x);
q = &*x;
can be
y = new int **(x); // &*x == x
q = x;
Function putArr
You have the function declaration as:
void putArr(int **&x, int &size1, int &size2)
It can be changed to:
void putArr(int **x, int size1, int size2)
without changing how you are using the variables.
Your code in the function seems strange. Did you mean for x[0] and x[1] to point to an array of size1 and size2 ints, respectively? If you did, the code would be:
x[0] = new int[size1];
x[1] = new int[size2];
If you don't mean the above, it's hard to figure out what you are trying to do with your code.
Function Input
You have the function declaration as:
void Input (int **&x, int *&arr, int &size1,int &size2, int a, int b)
It can be changed to:
void Input (int **x, int *arr, int &size1,int &size2, int a, int b)
without changing how you are using the variables.
You are calling a function checkVal, but your posted code doesn't have that function. It's not clear what that function is doing. You have the line
cout << "Please enter 2 non-negative integer values: "<< endl;
just before the calls to checkVal. Presumably, checkVal reads the input and stores them in size1 in the first call and size2 in the second call. It's not clear how the second argument to checkVal is used.
And then, you have the line:
cout << x[0];
It's not clear what you wish to accomplish from printing an int* to cout. Perhaps it was part of your debugging code. The line doesn't change anything else in the program. It's just strange to see it there.
Function summation
You have the function declaration as:
void summation(int ***&y, int *&arr)
It can be changed to:
void summation(int ***y, int *arr)
without changing how you are using the variables.
In this function, you have the expression:
asize = *(***(y) + **(y + 1));
What do you get when you evaluate ***(y)?
***(y) = **(*y) = **(x) = *(*x) = *(x[0]) = uninitialized value from the line:
x[0] = new int[size1];
You will get unpredictable behavior when you use an uninitialized value.
The second term of the line, **(y + 1) is the worse culprit.
You allocated memory for y as:
y = new int **(&*x);
It's a pointer to a single object of type int**, not an array. y+1 is not a valid pointer. Dereferencing (y+1) leads to undefined behavior. In your case, you are seeing exc_bad_access, which makes sense now since you are accessing memory that is out of bounds.
Since I don't know what you are trying to compute in that expression, it's hard for me to suggest something useful. I hope you have enough to take it from here.
I get a segmentation fault when reading the second element of h array inside the g function. Strangely, when debugging can I actually watch the array content. I think that besides this curious thing that shows that the data is there, I have done something wrong. Thanks in advance.
#include <iostream>
using namespace std;
void function(void function_passed(double* [], int), int n);
void g(double* [] ,int n_g);
int main()
{
function(g,5);
return 0;
}
void g(double* h[], int n_g)
{
for (int i = 0; i < n_g; i++)
cout << i << " "<< *h[i] << endl;
}
void function(void function_passed(double* [], int ), int n)
{
double * h = new double[n];
for (int i=0;i<n;i++)
h[i] = i + 10;
function_passed(&h,n);
delete[] h;
}
void func(void g(double* [],int n ), int n)
{
double * h = new double[n];
for (int i=0;i<n;i++)
h[i] = i;
g(&h,n);
delete[] h;
}
Operator precedence has bitten you. Inside g:
*h[i] is parsed as *(h[i]) but what you want is (*h)[i].
*h[i] is okay for the first iteration, but in the second one (and all subsequent) you're dereferencing an invalid pointer h+i.
On the second thought, you're actually invoking undefined behavior - pointer arithmetic is valid only between pointers that point to the same array.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int width = 100;
int height = 100;
float cam[] = {-1.1,-1.0,1.2};
float D[] = {0.2,0.2,-0.2};
float U[] = {0.0,1.0,0.0};
float* cross(float* v1,float* v2)
{
float el1[] = {(v1[1]*v2[2]-v1[2]*v2[1]),(v1[2]*v2[0]-v1[0]*v2[2]),(v1[0]*v2[1]-v1[1]*v2[0])};
return el1;
}
float* neg3(float* v)
{
float arr[3];
for(int i=0;i<3;i++)
arr[i] = 0.0-(v[i]);
return arr;
}
/*
float* cam_space(float* p)
{
float* e1 = cross(D,U);
float* e2 = cross(D,cross(U,D));
float* e3_n = D;
float ar[4];
ar[0] = e1[0]*p[0]+e1[1]*p[1]+e1[2]*p[2];
ar[1] = e2[0]*p[0]+e2[1]*p[1]+e2[2]*p[2];
ar[2] = -(e3_n[0]*p[0]+e3_n[1]*p[1]+e3_n[2]*p[2]);
ar[3] = p[3];
return ar;
}
*/
float* translate(float* p,float* v)
{
float arr1[3];
for(int i=0;i<=2;i++)
arr1[i] = p[i] + v[i];
return arr1;
}
int main()
{
float* poi;
poi = cam; //undo later
float* nc;
nc = neg3(cam);
cout<<" "<<nc[0]<<" "<<nc[1]<<" "<<nc[2]<<endl;
float arbit[3] = {0.1,0.1,0.1};
float* temp1;
temp1 = translate(poi,arbit);
//float* temp2;
//temp2 = cam_space(temp);
cout<<" "<<nc[0]<<" "<<nc[1]<<" "<<nc[2]<<endl;
cout<<" "<<poi[0]<<" "<<poi[1]<<" "<<poi[2]<<endl;
cout<<" "<<temp1[0]<<" "<<temp1[1]<<" "<<temp1[2]<<endl;
return 0;
}
As you can see, I am outputting nc twice. But both the values differ. The second time nc is displayed, it actually shows the temp1 value, and temp1 actually shows garbage values.
Any help?
float* translate(float* p,float* v)
{
float arr1[3];
for(int i=0;i<=2;i++)
arr1[i] = p[i] + v[i];
return arr1;
}// arr1 ceases to exist from this point.
You are returning the reference of a local variable, arr1. It resides on stack and gets de-allocated on the return of function call. But you are holding a reference to it which is yielding you garbage values. Instead new new[] arr1 and return it. Remember to delete[] it when you are done.
You are returning pointers to local variables left right and centre. Those variables go out of scope at the end of the function body, and the result is undefined behaviour.
A nice way of handling array-modifying functions is to pass the array as a parameter:
void modify_me(float arr[]) // or `modify_me(float * arr)`, same thing
{
arr[0] = 0.5;
arr[1] = -2.25;
}
int main()
{
float myarray[2];
modify_me(myarray); // now myarray[0] == 0.5, etc.
// ...
}
Since you're in C++, you could even use template magic:
template <unsigned int N>
void modify_me(float (&arr)[N])
{
static_assert(N == 3, "You're doing it wrong!"); // C++11 feature
arr[0] = /* ... */
}
Now you get a compile-time error if you try to call this with anything that's not an automatic array of size 3.
Instead of returning pointers to local variables you should return values.
Consider this:
struct V3 { float data[3]; }
V3 neg3(V3 v)
{
for(int i=0;i<3;i++)
v.data[i] = -v.data[i];
return v;
}
translate() returns a local pointer (converted from array type). So what temp1 is referring to, doesn't exist after the function translate() returns.
Same is the case with neg3() also.
If you're using C++, then std::vector<float> will solve all such problem.
You could write this:
std::vector<float> translate(const std::vector<float> & p, const std::vector<float> & v)
{
std::vector<float> vf(3);
for(int i=0;i <3;i++)
vf[i] = p[i] + v[i];
return vf; //semantically, it returns a copy of the local object.
}
Similarly, use std::vector whereever you're using float[3]. And don't use global variables.