allocating vectors in a function

  • Thread starter Bart Vandewoestyne
  • Start date
B

Bart Vandewoestyne

I'm trying to allocate 3 vectors within a function. This is what
I do:

I declare the three vectors as pointers to doubles:

double *Hx;
double *Hy;
double *Ez;

I then have the function that allocates the memory for the
vectors:

void allocate_maxwell_fields_2d(int K, int Np,
double *Hx, double *Hy, double *Ez) {

Hx = (double*) calloc(K*Np, sizeof(double));
Hy = (double*) calloc(K*Np, sizeof(double));
Ez = (double*) calloc(K*Np, sizeof(double));

}


And I call the function as follows:

allocate_maxwell_fields_2d(mesh->K, p_Np, Hx, Hy, Ez);

The call to the function seems to go fine, but when I get a segmentation
fault when i try to access for example Hx[0] after I called the allocation
function. Apparently, after the call to my allocate function, the Hx pointer
is not correctly set.

What am I doing wrong here?

Thanks!
Bart
 
I

Ian Collins

I'm trying to allocate 3 vectors within a function. This is what
I do:

I declare the three vectors as pointers to doubles:

double *Hx;
double *Hy;
double *Ez;

I then have the function that allocates the memory for the
vectors:

void allocate_maxwell_fields_2d(int K, int Np,
double *Hx, double *Hy, double *Ez) {

Hx = (double*) calloc(K*Np, sizeof(double));
Hy = (double*) calloc(K*Np, sizeof(double));
Ez = (double*) calloc(K*Np, sizeof(double));

}


And I call the function as follows:

allocate_maxwell_fields_2d(mesh->K, p_Np, Hx, Hy, Ez);

The call to the function seems to go fine, but when I get a segmentation
fault when i try to access for example Hx[0] after I called the allocation
function. Apparently, after the call to my allocate function, the Hx pointer
is not correctly set.

What am I doing wrong here?

A very common mistake, not passing pointers to your pointers!
 
B

Bart Vandewoestyne

I'm trying to allocate 3 vectors within a function. This is what
I do:

I declare the three vectors as pointers to doubles:

double *Hx;
double *Hy;
double *Ez;

I then have the function that allocates the memory for the
vectors:

void allocate_maxwell_fields_2d(int K, int Np,
double *Hx, double *Hy, double *Ez) {

Hx = (double*) calloc(K*Np, sizeof(double));
Hy = (double*) calloc(K*Np, sizeof(double));
Ez = (double*) calloc(K*Np, sizeof(double));

}


And I call the function as follows:

allocate_maxwell_fields_2d(mesh->K, p_Np, Hx, Hy, Ez);

The call to the function seems to go fine, but when I get a segmentation
fault when i try to access for example Hx[0] after I called the allocation
function. Apparently, after the call to my allocate function, the Hx pointer
is not correctly set.

What am I doing wrong here?

A very common mistake, not passing pointers to your pointers!

I'm afraid I still don't see my mistake. Let me tell you how I
am reasoning (for example for Hx).

I declare Hx as a 'pointer to double'. This means Hx is the
pointer, *Hx would be the value and &Hx would be the address of
the pointer.

I think my function declaration is right: i declare Hx to be a
pointer by writing double *Hx as function argument. Inside my
function, I need Hx (the pointer to double) and not *Hx (the
value) nor &Hx (the address of the pointer) because calloc
returns the pointer to double, which should be assigned to Hx.

When I call my function, i need to pass the pointer, not the
value of the pointer nor the address of the pointer, so i pass Hx
and not *Hx nor &Hx.

What is wrong in my reasoning and how do i correct my code?

Regards,
Bart
 
B

bart.c

Bart Vandewoestyne said:
On 07/ 2/10 11:23 PM, Bart Vandewoestyne wrote:
double *Hx;
double *Hy;
double *Ez;

I then have the function that allocates the memory for the
vectors:

void allocate_maxwell_fields_2d(int K, int Np,
double *Hx, double *Hy, double *Ez) {

Hx = (double*) calloc(K*Np, sizeof(double));
Hy = (double*) calloc(K*Np, sizeof(double));
Ez = (double*) calloc(K*Np, sizeof(double));
And I call the function as follows:

allocate_maxwell_fields_2d(mesh->K, p_Np, Hx, Hy, Ez);

The call to the function seems to go fine, but when I get a segmentation
fault when i try to access for example Hx[0] after I called the
allocation
What am I doing wrong here?

A very common mistake, not passing pointers to your pointers!

I'm afraid I still don't see my mistake. Let me tell you how I
am reasoning (for example for Hx).

I declare Hx as a 'pointer to double'. This means Hx is the
pointer, *Hx would be the value and &Hx would be the address of
the pointer.

I think my function declaration is right: i declare Hx to be a
pointer by writing double *Hx as function argument. Inside my
function, I need Hx (the pointer to double) and not *Hx (the
value) nor &Hx (the address of the pointer) because calloc
returns the pointer to double, which should be assigned to Hx.

When I call my function, i need to pass the pointer, not the
value of the pointer nor the address of the pointer, so i pass Hx
and not *Hx nor &Hx.

What is wrong in my reasoning and how do i correct my code?

You're passing a copy of pointer Hx (and Hy, Ez) to your allocate function.
That function allocates space and updates it's *copies* of these pointers.
The original Hx, etc. are unchanged.

The function signature needs to use double **Hx, and you need to pass &Hx.
Inside your allocate function, you then use *Hx = ... etc.
 
B

Bart Vandewoestyne

You're passing a copy of pointer Hx (and Hy, Ez) to your allocate function.
That function allocates space and updates it's *copies* of these pointers.
The original Hx, etc. are unchanged.

The function signature needs to use double **Hx, and you need to pass &Hx.
Inside your allocate function, you then use *Hx = ... etc.

OK. I think I got it. The main problem was that I passed
*copies* of my pointers to doubles, and so after the return of
the function call, the original ones hadn't changed. To get
things to work, i didn't have to change the declaration of my
pointers:

double *Hx;
double *Hy;
double *Ez;

but I did change the function definition to:

void allocate_maxwell_fields_2d(int K, int Np,
double **Hx, double **Hy, double **Ez) {

*Hx = (double*) calloc(K*Np, sizeof(double));
*Hy = (double*) calloc(K*Np, sizeof(double));
*Ez = (double*) calloc(K*Np, sizeof(double));

}

and i now call my function as

allocate_maxwell_fields_2d(mesh->K, p_Np, &Hx, &Hy, &Ez);

which seems to work.

Although I think this is the right way to do it now, please correct me
if there's still something wrong or if I'm using bad coding practices.

Regards,
Bart
 
B

blmblm

OK. I think I got it. The main problem was that I passed
*copies* of my pointers to doubles, and so after the return of
the function call, the original ones hadn't changed.

Yes. This is how C works -- parameters are passed by value.
(Someone will be along in a minute to correct me if there are
situations in which it's not true!)

Just thought I'd mention the general rule, which applies equally
to parameters that aren't pointers. It's why, for example, if you
use scanf to get input from stdin, you have to pass it pointers to
the variable(s) you want to modify, rather than just their names.

[ snip ]
 
M

Morris Keesan

On Fri, 02 Jul 2010 08:06:31 -0400, Bart Vandewoestyne
void allocate_maxwell_fields_2d(int K, int Np,
double **Hx, double **Hy, double **Ez)
{
*Hx = (double*) calloc(K*Np, sizeof(double));
*Hy = (double*) calloc(K*Np, sizeof(double));
*Ez = (double*) calloc(K*Np, sizeof(double));
}

and i now call my function as

allocate_maxwell_fields_2d(mesh->K, p_Np, &Hx, &Hy, &Ez);

which seems to work.

Although I think this is the right way to do it now, please correct me
if there's still something wrong or if I'm using bad coding practices.

The way you're calling allocate_maxwell_fields_2d is now correct (passing
the addresses of the things you want the function to modify), but the way
you're allocating the vectors makes little sense. calloc() is defined
as setting the contents of the allocated space to "all bits zero", but
the language does not define the meaning of a double with all bits zero.
If you really want the allocated doubles to have the value of 0.0, then
in order for your code to be portable, you'll have to initialize those
values explicitly. If you don't care what the initial values of the
vectors are, then using calloc is simply a waste of the processing time
used to zero the bits. Better would be to write

*Hx = malloc(K * Np * sizeof(double));
*Hy = malloc(K * Np * sizeof(double));
*Ez = malloc(K * Np * sizeof(double));

and initialize the vector contents in a for loop, if desired.

Notice also that casting the return value of calloc or malloc is
unnecessary
in C. Experts disagree about whether it's good style. Also, by writing

*Hx = malloc(K * Np * sizeof(**Hx));

you would guarantee that the correct size is being used, and save yourself
some editing and/or errors if at some time in the future you decided to
change the type of Hx (e.g. to (float) or (long double)).
 
M

Moi

OK. I think I got it. The main problem was that I passed *copies* of
my pointers to doubles, and so after the return of the function call,
the original ones hadn't changed. To get things to work, i didn't have
to change the declaration of my pointers:

double *Hx;
double *Hy;
double *Ez;

but I did change the function definition to:

void allocate_maxwell_fields_2d(int K, int Np,
double **Hx, double **Hy, double **Ez)
{

*Hx = (double*) calloc(K*Np, sizeof(double)); *Hy = (double*)
calloc(K*Np, sizeof(double)); *Ez = (double*) calloc(K*Np,
sizeof(double));

}

and i now call my function as

allocate_maxwell_fields_2d(mesh->K, p_Np, &Hx, &Hy, &Ez);

which seems to work.

Although I think this is the right way to do it now, please correct me
if there's still something wrong or if I'm using bad coding practices.

Correct.

Minor style issue: IMHO you are confusing yourself by using the same names
for the (global?) pointer variables and the (formal) arguments of the function.
To me, it would be much clearer if the program used different names, for example:

void allocate_three_things(int count, int size, double**the_x, double **the_y, double **the_z) {
*the_x = malloc ( count*size * sizeof **the_x);
....
}

The function call could then look like:

allocate_three_things(mesh->K, p_Np, &Hx, &Hy, &Ez);

HTH,
AvK
 
C

Chad

(e-mail address removed) wrote:



I hope I'm in time. :)

Parameters are not passed at all. *Arguments* are passed by value. This
is true in all cases. Actually, I'm being rather picky, since even the
Standard refers to the term "actual parameter" to describe "argument",
but it is a deprecated usage (which, therefore, may well be removed from
future editions of the Standard).

But yes, you are basically correct - *ALL* function arguments are passed
by value. There are no circumstances in which this is not the case, at
all, ever ever ever.

<snip>

Wouldn't the parameters get evaluated to some value before they get
passed as arguments?
 
R

Richard Bos

Bart Vandewoestyne said:
void allocate_maxwell_fields_2d(int K, int Np,
double *Hx, double *Hy, double *Ez) {

Hx = (double*) calloc(K*Np, sizeof(double));
Hy = (double*) calloc(K*Np, sizeof(double));
Ez = (double*) calloc(K*Np, sizeof(double));

Apart from what the others have written:

1. Don't cast the result of calloc() (or malloc(), or realloc()). It is
not necessary in properly written C. Any unnecessary cast is bad style,
mainly because it decreases the attention value of necessary casts.
2. Don't use calloc() for floating point values in the first place.
All-bits-zero is not guaranteed to be a legal floating point value - it
may be a trap representation. You may presume that it usually isn't, but
people do get bitten by "usually"s which turn out to be "but not today".
Assign known-correct values instead.

Neither of those would have caused the error you've been seeing, but the
first could cause trouble further along the line if you've been
negligent elsewhere (e.g., by not #including the necessary headers) and
the second could cause real problems if your code is ported to a system
with a "different" floating point implementation.

Richard
 
K

Keith Thompson

Bart Vandewoestyne said:
but I did change the function definition to:

void allocate_maxwell_fields_2d(int K, int Np,
double **Hx, double **Hy, double **Ez) {

*Hx = (double*) calloc(K*Np, sizeof(double));
*Hy = (double*) calloc(K*Np, sizeof(double));
*Ez = (double*) calloc(K*Np, sizeof(double));

}

and i now call my function as

allocate_maxwell_fields_2d(mesh->K, p_Np, &Hx, &Hy, &Ez);

which seems to work.

Although I think this is the right way to do it now, please correct me
if there's still something wrong or if I'm using bad coding practices.

What happens if calloc (or malloc, if you follow the suggestions posted
later in the thread) fails to allocate memory?

malloc() returns a null pointer on failure. It's reasonable for
allocate_maxwell_fields_2d() to set *Hx, *Hy, and/or *Ez to null
on an allocation failure (and this behavior should be documented),
but you need to check whether the the allocation succeeded at some
point before you try to use the allocated memory.
 

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,780
Messages
2,569,611
Members
45,276
Latest member
Sawatmakal

Latest Threads

Top