allocate memory for pointer

X

xuatla

I encountered "segmentation fault" and I checked my code, found the
following problem:

I want to reallocate memory for an array.
I defined the following function:

int reallocateMemory( double *array, int newsize )
{
if (array) delete[] array;

array = new double[newsize];

return 1;
}

Now,
int main()
{
double *a = new double[2], *b = new double[10];

cout << a << endl; // address of a. (1)

for ( int i = 0; i < 10; i++ ) b = i; // b = {0,1,....,9}

reallocateMemory( a, 10 );

cout << a << endl; // the address of a is same as (1)! :(

for ( int i = 0; i < 10; i++ ) a = 0.1*i;

for ( int i = 0; i < 10; i++ )
cout << a << " ";
cout << endl; // fine, a is 0,0.1,...,0.9

for ( int i = 0; i < 10; i++ )
cout << b << " ";
cout << endl;

// error: output = 0.3,0.4,...,0.9,7,8,9

return 0;
}

So the memory of "a" is not reallocated although I call the function to
change it.

What I think is that passed-by-pointer in function will change the
parameter directly. Therefore after I call the function
reallocateMemory, "a" should be changed. But it seems that the result is
same as passed-by-value.

What's the problem in my function?

Thank you for your help!

X
 
S

Sharad Kala

xuatla said:
I encountered "segmentation fault" and I checked my code, found the
following problem:

I want to reallocate memory for an array.
I defined the following function:

int reallocateMemory( double *array, int newsize )
{
if (array) delete[] array;

array = new double[newsize];

How do you return array back to main now?
return 1;
}

Now,
int main()
{
double *a = new double[2], *b = new double[10];

cout << a << endl; // address of a. (1)

for ( int i = 0; i < 10; i++ ) b = i; // b = {0,1,....,9}

reallocateMemory( a, 10 );


After this function a points to deleted memory. Henceforth trying anything
on that memory is UB.

So it resolve the problem change reallocate to -
int reallocateMemory( double *&array, int newsize )
^^^^^^^^
You are now paasing a reference to a pointer. Any changes now made to array
will be reflected back in main.

-Sharad
 
J

John Harrison

I encountered "segmentation fault" and I checked my code, found the
following problem:

I want to reallocate memory for an array.
I defined the following function:

int reallocateMemory( double *array, int newsize )
{
if (array) delete[] array;

array = new double[newsize];

return 1;
}

Now,
int main()
{
double *a = new double[2], *b = new double[10];

cout << a << endl; // address of a. (1)

for ( int i = 0; i < 10; i++ ) b = i; // b = {0,1,....,9}

reallocateMemory( a, 10 );

cout << a << endl; // the address of a is same as (1)! :(

for ( int i = 0; i < 10; i++ ) a = 0.1*i;

for ( int i = 0; i < 10; i++ )
cout << a << " ";
cout << endl; // fine, a is 0,0.1,...,0.9

for ( int i = 0; i < 10; i++ )
cout << b << " ";
cout << endl;

// error: output = 0.3,0.4,...,0.9,7,8,9

return 0;
}

So the memory of "a" is not reallocated although I call the function to
change it.

What I think is that passed-by-pointer in function will change the
parameter directly. Therefore after I call the function
reallocateMemory, "a" should be changed. But it seems that the result is
same as passed-by-value.


Yes, pointers are passed by value just like everything else.
What's the problem in my function?

You are passing by value. If you want to use a function to change that
value of a variable you have three alternatives.

1) Use a return value

double* reallocateMemory( double *array, int newsize )
{
delete[] array;
return new double[newsize];
}

a = reallocateMemory( a, 10 );

2) Use a reference

void reallocateMemory( double*& array, int newsize )
{
delete[] array;
array = new double[newsize];
}

reallocateMemory( a, 10 );

3) Use a pointer (in your case this would be a pointer to a pointer)

void reallocateMemory( double** array, int newsize )
{
delete[] *array;
*array = new double[newsize];
}

reallocateMemory( &a, 10 );


BTW it is not necessary to test for NULL before deleteing a pointer

if (ptr) delete[] ptr;

works exactly the same as

delete[] ptr;

Deleting NULL is guaranteed to have no effect.

john
 
P

Patrik Stellmann

[...]
int reallocateMemory( double *array, int newsize )
{
if (array) delete[] array;

array = new double[newsize];

return 1;
} [...]

What's the problem in my function?
your function changes only the local variable array which has no
influence to your variable a in main. Changing the functiondeclaration to
int reallocateMemory( double *&array, int newsize )
should do the trick. Now not the value of a is passed to the function
but the reference of it so you're able to modify its value...
 
X

xuatla

Thanks all of you for the kind help.

I made a mistake. As I mentioned I thought passed-by-pointer is
different with passed-by-value and the change will be kept after calling
the function. Now I know I made a mistake. If "a" is a double value, not
an array, then

testfun( double *a)
{ *a = newvalue; }
and
{
...
double a;
testfun(&a);
}
will change the value of a. But what I used is the pointer to an array.
So it's differnt.

Thanks for pointing out my mistake and giving me the good answers.

I have one more related (and naive) question
(1) double* a --- a is a double array
(2) double *a --- a is a double pointer

what's the difference of (1) & (2)? both a are address and one points to
an array while another points to a value. is there any other characters
in expression tell c++ that there're different? Thanks!

X

John said:
I encountered "segmentation fault" and I checked my code, found the
following problem:

I want to reallocate memory for an array.
I defined the following function:

int reallocateMemory( double *array, int newsize )
{
if (array) delete[] array;

array = new double[newsize];

return 1;
}

Now,
int main()
{
double *a = new double[2], *b = new double[10];

cout << a << endl; // address of a. (1)

for ( int i = 0; i < 10; i++ ) b = i; // b = {0,1,....,9}

reallocateMemory( a, 10 );

cout << a << endl; // the address of a is same as (1)! :(

for ( int i = 0; i < 10; i++ ) a = 0.1*i;

for ( int i = 0; i < 10; i++ )
cout << a << " ";
cout << endl; // fine, a is 0,0.1,...,0.9

for ( int i = 0; i < 10; i++ )
cout << b << " ";
cout << endl;

// error: output = 0.3,0.4,...,0.9,7,8,9

return 0;
}

So the memory of "a" is not reallocated although I call the function
to change it.

What I think is that passed-by-pointer in function will change the
parameter directly. Therefore after I call the function
reallocateMemory, "a" should be changed. But it seems that the result
is same as passed-by-value.



Yes, pointers are passed by value just like everything else.
What's the problem in my function?

You are passing by value. If you want to use a function to change that
value of a variable you have three alternatives.

1) Use a return value

double* reallocateMemory( double *array, int newsize )
{
delete[] array;
return new double[newsize];
}

a = reallocateMemory( a, 10 );

2) Use a reference

void reallocateMemory( double*& array, int newsize )
{
delete[] array;
array = new double[newsize];
}

reallocateMemory( a, 10 );

3) Use a pointer (in your case this would be a pointer to a pointer)

void reallocateMemory( double** array, int newsize )
{
delete[] *array;
*array = new double[newsize];
}

reallocateMemory( &a, 10 );


BTW it is not necessary to test for NULL before deleteing a pointer

if (ptr) delete[] ptr;

works exactly the same as

delete[] ptr;

Deleting NULL is guaranteed to have no effect.

john
 
S

Sharad Kala

xuatla said:
I have one more related (and naive) question
(1) double* a --- a is a double array
(2) double *a --- a is a double pointer

No both are pointers.
double* a, b;
a is a pointer to double while b is a double.
Arrays are indicated by the subscript operator [] like arr[10] . Arrays
decay down to pointers though.

-Sharad
 
J

John Harrison

xuatla said:
Thanks all of you for the kind help.

I made a mistake. As I mentioned I thought passed-by-pointer is
different with passed-by-value and the change will be kept after calling
the function. Now I know I made a mistake. If "a" is a double value, not
an array, then

testfun( double *a)
{ *a = newvalue; }
and
{
...
double a;
testfun(&a);
}
will change the value of a. But what I used is the pointer to an array.
So it's differnt.

Thanks for pointing out my mistake and giving me the good answers.

I have one more related (and naive) question
(1) double* a --- a is a double array
(2) double *a --- a is a double pointer

what's the difference of (1) & (2)?

There is no difference at all. Whitespace is not significant in C++. Some
people say that stylistically 2 is better than 1 and a few say the opposite,
but that's all it is, a style issue.
both a are address and one points to
an array while another points to a value. is there any other characters
in expression tell c++ that there're different? Thanks!

Both are pointers. Strictly speaking if you want a pointer to an array its a
different syntax

int a[5] = { 1, 2, 3, 4, 5 };
int (*p)[5] = &a; // a pointer to an array
cout << (*p)[0]; // prints 1

but true pointers to arrays are not used very much, so people often say
pointer to an array when really they mean a pointer which happens to be
pointing to the first element of an array.

int a[5] = { 1, 2, 3, 4, 5 };
int *p = a; // a pointer which is pointing to the first element of a
cout << *p; // prints 1

john
 
J

JKop

John Harrison posted:
xuatla said:
Thanks all of you for the kind help.

I made a mistake. As I mentioned I thought passed-by- pointer is
different with passed-by-value and the change will be kept after
calling the function. Now I know I made a mistake. If "a" is a double
value, not an array, then

testfun( double *a)
{ *a = newvalue; } and { ...
double a;
testfun(&a);
}
will change the value of a. But what I used is the pointer to an
array. So it's differnt.

Thanks for pointing out my mistake and giving me the good answers.

I have one more related (and naive) question
(1) double* a --- a is a double array
(2) double *a --- a is a double pointer

what's the difference of (1) & (2)?

There is no difference at all. Whitespace is not significant in C++.
Some people say that stylistically 2 is better than 1 and a few say the
opposite, but that's all it is, a style issue.
both a are address and one points to
an array while another points to a value. is there any other
characters in expression tell c++ that there're different? Thanks!

Both are pointers. Strictly speaking if you want a pointer to an array
its a different syntax

int a[5] = { 1, 2, 3, 4, 5 };
int (*p)[5] = &a; // a pointer to an array
cout << (*p)[0]; // prints 1

but true pointers to arrays are not used very much, so people often say
pointer to an array when really they mean a pointer which happens to be
pointing to the first element of an array.

int a[5] = { 1, 2, 3, 4, 5 };
int *p = a; // a pointer which is pointing to the first element of a
cout << *p; // prints 1

john

The following is a mess. What I tried to get was a
multidemensional array with new.

It compiles, but don't ask me what it does. Note how at one
point I've write int[5][5][5][5], as opposed to just three
5's, it won't compile otherwise and I don't know why.

Anyway,


#ifndef INCLUDE_ACCESSOR_CAST
#define INCLUDE_ACCESSOR_CAST

template<typename TO, class FROM>
inline TO& accessor_cast(FROM& from)
{
return *(reinterpret_cast<TO*>(&from));
}

template<typename TO, class FROM>
inline const TO& accessor_cast(const FROM& from)
{
return *(reinterpret_cast<const TO*>(&from));
}

#endif


int main()
{
int* blah = new int[125];

int (*krt)[5][5][5] = accessor_cast<int([5][5][5][5])>
(blah);

*krt[1][3][2] = 45;

delete [] blah;
}


-JKop
 
J

John Harrison

The following is a mess. What I tried to get was a
multidemensional array with new.

It compiles, but don't ask me what it does. Note how at one
point I've write int[5][5][5][5], as opposed to just three
5's, it won't compile otherwise and I don't know why.

Anyway,


#ifndef INCLUDE_ACCESSOR_CAST
#define INCLUDE_ACCESSOR_CAST

template<typename TO, class FROM>
inline TO& accessor_cast(FROM& from)
{
return *(reinterpret_cast<TO*>(&from));
}

template<typename TO, class FROM>
inline const TO& accessor_cast(const FROM& from)
{
return *(reinterpret_cast<const TO*>(&from));
}

#endif


int main()
{
int* blah = new int[125];

int (*krt)[5][5][5] = accessor_cast<int([5][5][5][5])>
(blah);

*krt[1][3][2] = 45;

delete [] blah;
}

int[5][5][5][5] has 625 elements and your original array has 125. I think
you meant this

int main()
{
int* blah = new int[125];
int (*krt)[5][5] = accessor_cast<int[5][5][5]> (blah);

krt[1][3][2] = 45;
delete [] blah;
}

It just an example of an array to pointer conversion. int[5][5][5] is an
array of size 5, where each element happens to be an int[5][5]. Therefore
int[5][5][5] can convert to a pointer to int[5][5]. The syntax for pointer
to int[5][5] is int (*)[5][5].

Another way of writing your cast would be

int (*krt)[5][5] = accessor_cast<int(*)[5][5]> (blah);

Nothing was compiled so apologies in advance for any stupid mistakes.

john
 
J

JKop

Success! I think...

I got three seperate codes to compile, but only one would
run without run-time errors, ie. bad memory
access/allocation.

Here it is:

#ifndef INCLUDE_ACCESSOR_CAST
#define INCLUDE_ACCESSOR_CAST

template<typename TO, class FROM>
inline TO& accessor_cast(FROM& from)
{
return *(reinterpret_cast<TO*>(&from));
}

template<typename TO, class FROM>
inline const TO& accessor_cast(const FROM& from)
{
return *(reinterpret_cast<const TO*>(&from));
}

#endif


int main()
{
int* blah = new int[125];

int (*krt)[5][5] = accessor_cast<int(*)[5][5]> (blah);

krt[1][3][2] = 45;

delete [] blah;
}



Are we the first people to get a multidimensional array out
of the heap?!


Next step is making a template!


(But I still don't understand why we've turned [5][5][5]
into [5][5] in the casts.)


-JKop
 
J

JKop

JKop posted:
(But I still don't understand why we've turned [5][5][5]
into [5][5] in the casts.)

I just realized why. For instance one can:

int blah[5];

blah[72] = 6;

The only reason the further 5's are required is to give
shape to the array!


-JKop
 
J

John Harrison

JKop said:
Success! I think...

Looks good to me.
Are we the first people to get a multidimensional array out
of the heap?!

I don't think so somehow.
Next step is making a template!

Check out this http://www.boost.org/libs/multi_array/doc/index.html
(But I still don't understand why we've turned [5][5][5]
into [5][5] in the casts.)

It's the same reason that you lose a pair of brackets in this

int a[5];
int* p = a;

When an array decays to a pointer you lose one dimension of the array. So 1d
int array goes to pointer to int, 2d int array goes to pointer to 1d int
array, 3d int array goes to pointer to 2d int array etc. etc.

john
 
R

Rolf Magnus

xuatla said:
Thanks all of you for the kind help.

I made a mistake. As I mentioned I thought passed-by-pointer is
different with passed-by-value and the change will be kept after
calling the function. Now I know I made a mistake. If "a" is a double
value, not an array, then

testfun( double *a)
{ *a = newvalue; }
and
{
...
double a;
testfun(&a);
}
will change the value of a. But what I used is the pointer to an
array. So it's differnt.

No, the difference is that in one case, you changed what the pointer
points to, in the other case you try to change the pointer itself. If
you'd write:

testfun( double *a)
{
delete a;
a = new double(3.5);
}

You'd get the same problem you got with your array.
 
D

Default User

xuatla said:
I encountered "segmentation fault" and I checked my code, found the
following problem:

I want to reallocate memory for an array.


Others have pointed out the actual error in the code. The bigger
question is, why are you using dynamic arrays at your stage of learning?
You should be using std::vector unless you have a very good reason for
doing something else. Yes, someday you'll need to know how to do that,
but not as a newbie. You are working in C++, not C.




Brian Rodenborn
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,111
Latest member
KetoBurn
Top