?
Solved

Checking addresses of fortran passed variables in a c func

Posted on 2003-12-01
10
Medium Priority
?
397 Views
Last Modified: 2013-11-08
Hi,

I'm having some trouble with some fortran code. Arithmetic exception at the return from a subroutine. This only occurs with optimization; if I turn on debugging it works fine. I've checked everything I possibly can, but I don't see anything wrong. It could be something farther up the line is awry.

I suspect that memory is a bit screwed up. The code is too big to have the cross reference checker available on the sun do this for me. It bombs at the end, complaining of too many files or something like that.

I thought I would write a generic c function that would check the addresses of passed variables before a call, and then call it again once inside the routine, via some sort of c function. I could place this at points in the code which I suspect are giving me problems.

I don't know if this is possible in fortran, but I don't think so. So I'm looking to c.

Since fortran always passes by reference, or address, and c will allow me access to the address of the pointer, it seems the way to go.

What I've done so far is copied the signature of the fortran subroutine call into a call to a c routine, declared the integer variables as int *'s, real variables as float *'s, and double precision variables as double *'s. Then I store the addresses of the variables (first element in array case) in a long int on the c side. But they all have the same value?! What am I doing wrong? For instance, here is one line which is supposed to store an address:

i1[3] = (long int*) rtest;

i1 is declared as long int, and in this particular case rtest is coming from fortran declared as real, and declared as float* on the c side.

If I print out the i1's, they all have the same value.
What stupid thing am I doing wrong here?
I've also tried it without the cast - no luck.

Once I have this going, I'm wondering if there's a more robust way of doing this. Something that would work regardless of the number of variables being passes...


Thanks very much!
Skip Egley
0
Comment
Question by:egley
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
10 Comments
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 9855077

One thing that you're doing is setting i1[] to a value instead of an address.  If you're convinced that you have a parameter problem with a fortran program, you need to check the addresses being passed, not the value at the address.

void *i1[ArraySize];

i1[3] = &rtest;


Also, remember that when you recast something, the compiler generates the code to convert it from its "native" state to the data type that the cast indicates.

float v = 3.14159;
int i;

i = (int) v;

All you've done is trunctate v to 3 and stored it into i.  C will do this without the cast.


Kent

0
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 9855099
hi egley,

Another thing, many FORTRAN compilers have an addr() macro/function that will return the address of a variable.  It's a run-time evaluation so it returns a memory address.  You might be able to take advantage of this.

I recall some very old FORTRAN code where addr() was used to march through memory looking for "something".  Memory on that system was not virtual so the first address of a program space was 0.  Defining an array and indexing into it "out of bounds" made the entire job's memory available to the program.

      int K(1)

      do 10 i = 1, 10000
 10  IntVal = K(i - addr(K) - 1)

Dunno, but this trick might help, too.


Kent
0
 

Author Comment

by:egley
ID: 9859464
Hi Kent,

Thanks for the comment.

I thought that if they are coming in as pointers, I didn't use the & operator to obtain the address of the thing pointed to. I just used the pointer without the dereference operator (i.e., *). Is this not true? All variables coming into the c routine are declared as pointers, which I believe is the correct way to handle variables coming from fortran. Using the & operator on a pointer would give me the address of the pointer, no?

I will try this addr() on my fortran compiler...

Thanks again,
Skip
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 46

Expert Comment

by:Kent Olsen
ID: 9859667

Hi Skip,

You're right.  I misread your statement about how you'd declared the C function.  But this does bring up another possibility.  :)


Func(int *a, char *b, long *c, int *d, int *e)
{
  char * Ptr;

  Ptr = (char *) &a;

/*
  *Ptr is a
  *(Ptr+1) is b (recast as necesary)
  *(Ptr+2) is c
  etc...
*/

}

Kent
0
 

Author Comment

by:egley
ID: 9860210
Hi Kent,

Your 'possibility' spurred a thought.
Is there a problem to simply declare all received variables on the c side as char *'s? I really only want the address of the first element in the case of an array. I don't care if they  are actually doubles, floats, or whatever. But I don't understand exactly what is returned.

I mean if I pass a double precision array a, and then print out the address on the c side, would it be the same whether it was a double precision array or an integer array or a float array? Does it give the address of the first byte?

Thanks,
Skip
0
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 9860486

Hi Skip,

You can certainly do that.  Pointers are pointers are pointers.  It's only how you use the object that the pointer references that suggests a difference.  (The difference is the usage of the referenced object.)

That 'possibility' can be simplified:

Func(int *a, char *b, long *c, int *d, int *e)
{
  char *Ptr[];

  Ptr = (char **) &a;

/*
  Ptr[0] is a
  Ptr[1] is b (recast as necesary)
  Ptr[2] is c
  etc...
*/

}

Kent
0
 

Author Comment

by:egley
ID: 9861378

Kent,

Casting all of them to char *'s appears to work fine.
I've checked the addresses of all passed arrays and variables right before the call, then again when I'm in the subroutine.

The good news is they are the same.
The bad news is that some of them are negative.
This is not possible is it?

I'm a bit worried about misinterpreting the hex addresses when declaring as char and they end up coming out signed, and the sign being negative when it shouldn't actually be negative if interpreted correctly.

Skip
0
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 9861620

Hi Skip,

The sign bit doesn't necessarily mean a problem.  What are some of the addresses?

Kent
0
 

Author Comment

by:egley
ID: 9861983

Kent,

THey typically are between 100-200 million when printed out, except for the negative ones which are typically only a couple of milliong with a negative sign.

Here's a few of them, including a negative one.

Address 24: 188638432
Address 25: 159232664
Address 26: -4262840
Address 27: 190726448


Think these are OK?

Skip
0
 
LVL 46

Accepted Solution

by:
Kent Olsen earned 1400 total points
ID: 9862027

:)

Addresses are usually printed in hex.

188638423  B3E64E0
159232664  97DB298
-4262840    FFBEF448
190726448  B5E4130

Three of these addresses are positive, as they are only 28 bits in length.  The 32-bit address certainly seems reasonable, too.

I think that they are just fine.  You can test Address 26 just by trying to reference it, but I don't expect any problem.
Kent
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
There is an easy way, in .NET, to centralize the treatment of all unexpected errors. First of all, instead of launching the application directly in a Form, you need first to write a Sub called Main, in a module. Then, set the Startup Object to th…
The viewer will learn how to implement Singleton Design Pattern in Java.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question