Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29235 Discussions

Can structures be copied in fortran?

jjfait
Beginner
3,977 Views
Hi, I am using legacy fortran code and it seems that TYPE structures are copied in many places using the scheme struct1=struct2. Then pointers are deallocated from struct1 (which are really pointers or copies of pointers of struct2). My question is, is struct1 copied I would think it is just pointed to struct2. This scheme has worked for many years but when calling the fortran dll from c#, i many times seems to get a Attempted to Read or Write Protected Memory error. Any help or advice is appreciated.
Jeremy

Maybe this isnt the best explanation so i'll include the code:

module display
use picturedata
type (picture), SAVE :: pic(50), pictemp
...
end module display

module picturedata
use bitmaptypes
type picture
integer nx,ny
real*4,pointer :: array(:,:)=>Null()
...
end

Then, the project will use display. Creating pic(2)%array, pic(2)%nx ... and calling pic(1)=pic(2), this seems to copy the structure to pic(1) and then pic(1)%array is deallocated and allocated. This seems to work with the legacy code, but when calling from c# i get the accessing proctected memory.
0 Kudos
18 Replies
Steven_L_Intel1
Employee
3,977 Views
If you assign a derived type (structure), pointers are simply copied - there is no deallocation/reallocation. However, ALLOCATABLE arrays have the data copied, with the left side being (re) allocated to the proper shape if required.

So, if you copy a structure with pointers, and then deallocate the pointers in one, the pointers in the other are no longer defined. This doesn't mean they are zeroed - it simply means that you are not allowed to reference them.
0 Kudos
jjfait
Beginner
3,977 Views
If you assign a derived type (structure), pointers are simply copied - there is no deallocation/reallocation. However, ALLOCATABLE arrays have the data copied, with the left side being (re) allocated to the proper shape if required.

So, if you copy a structure with pointers, and then deallocate the pointers in one, the pointers in the other are no longer defined. This doesn't mean they are zeroed - it simply means that you are not allowed to reference them.
Ok, so the statement pic(1)=pic(2) is simpy a pointer to pic(2) right, not a structure copy?
What doesnt make sense to me is if you call pic(1)=pic(2) and then deallocate(pic(1)%array), the array of pic two (pic(2)%array) still exists.
Finally why does this work as a fortran executible, but crashes when run as a c# dll?
Thanks a lot. Jeremy
0 Kudos
Steven_L_Intel1
Employee
3,977 Views

No, I didn't say that. When you write pic(1)=pic(2), each member of pic(2) gets copied to the corresponding member of pic(1). Since one of those members is a pointer, the pointer gets copied as well.

In the situation you describe, pic(2)%array is a pointer to deallocated storage. It may seem to "exist", but it is an error to try to reference it and that storage may end up being used for something else.

If you are referencing through undefined pointers, all bets are off.
0 Kudos
jjfait
Beginner
3,977 Views
Thanks Steve
0 Kudos
jjfait
Beginner
3,977 Views
Actually i had one last question, according to my example above, if i simply allocate pic(2)%array and with an assignment pic(2)%array=pic(1)%array, will that copy the array or will the pointer by pointed to pic(1),thanks
Jeremy
0 Kudos
Steven_L_Intel1
Employee
3,977 Views

That will copy the data, not the pointer.
0 Kudos
jjfait
Beginner
3,977 Views

That will copy the data, not the pointer.
Is there a special case with multi-dimensional arrays? I specifically deallocate (if associated) and allocate pic(2)%array to the size of pic1 and then set pic(2)%array=pic(1)%array to copy the array and i get a stack overflow error??? Is there an error because i'm using two dim. arrays. thanks
0 Kudos
tom_p
Beginner
3,977 Views
Quoting - jjfait
Is there a special case with multi-dimensional arrays? I specifically deallocate (if associated) and allocate pic(2)%array to the size of pic1 and then set pic(2)%array=pic(1)%array to copy the array and i get a stack overflow error??? Is there an error because i'm using two dim. arrays. thanks

It's a special case with derived types. As soon as the arrays in an arrays assignment are components of a derived type, the Intel compiler always creates a temporary (see this thread: http://software.intel.com/en-us/forums/showthread.php?t=66011).

You can use the compiler option -heap-arrays to get rid of the stack overflow, but of course the temporary is still created. If you want to avoid this because it uses more memory and is slower, you can use DO-loops to copy the array.

0 Kudos
jjfait
Beginner
3,977 Views
Thanks Tom, that has solved this problem, but i have another one that is very confusing. Maybe i should move this one to a new thread. I took everything out of the subroutine because something has operating incorrectly. This code has the "=" operator overloaded to call a subroutine below inside of module display:
interface assignment(=)
subroutine picture_to_picture(outpic,inpic)
use picturemod
type (picture),intent(inout)::outpic
type (picture),intent(in)::inpic
end subroutine picture_to_picture
end interface

subroutine picture_to_picture(outpic,inpic)
use picturemod
implicit none
type (picture),intent(inout):: outpic
type (picture),intent(in):: inpic
integer shape2(2)
integer shape1(1),i,j
write(11,*)'in pic to pic'
end subroutine picture_to_picture

As you can see this function does nothing but print that it came in. Now when i call for a picture to be = to another it works everytime except for the certain case pic(3) = pictemp. With any pic number, ex pic(1),pic(2),...
pic(15)=pic(10)
pic(4)=pic(2)
pictemp=pic(3)
pic(20)=pic(1)
pic(3)=pictemp
pic(20)=pic(1)
Now all of these work except the line pic(3)=pictemp, and it always gives a stack overflow error at that line if i move it around. These are both of thetype (picture).It doesn't give an error if i use the compiler option -heap-arrays, but that seem like it would solve the problem. This make absolutely no sense to me.
0 Kudos
jjfait
Beginner
3,977 Views
This type of operation must not be very well supported because i found another error in the compiler. Say you call the code below:

subroutine crash()
use display
implicit none
integer i
pic(15)=pic(10)
end

This will result in :Error: This is either an invalid statement, a declaration statement that is ordered incorrectly, or a null procedure statement. This will happen if this is the first line of the subroutine. If you put a line in front of it say, i=2, then it will compile fine. I no longer trust the functionality of overloading the "=" operator and think i'll have to change it everywhere in the code.

0 Kudos
Steven_L_Intel1
Employee
3,977 Views

Where is "pic" declared? I think you have an error in the code - the compiler thinks that "pic" is a function as it is not declared as an array.
0 Kudos
jjfait
Beginner
3,977 Views

Where is "pic" declared? I think you have an error in the code - the compiler thinks that "pic" is a function as it is not declared as an array.
module display
use picturedata
type (picture), SAVE :: pic(50), pictemp
end module display

module picturedata
type picture
integer nx,ny ....
real*4,pointer :: array(:,:)=>Null()
end

So pic is a derived type that has already has been filled in and if called as the first line of the subroutine iget a compiler error but called as the second line it's fine, doesn't make sense. Also if i use pic(number)=pictemp, many times i get a stack overflow error, but i can call pic(num)=pic(num) or pictemp=pic(num) without the error, also doesn't make sense.
0 Kudos
Steven_L_Intel1
Employee
3,977 Views
Please provide a short (if possible) but complete source that demonstrates the problem. Paraphrases are often missing some key element.
0 Kudos
jjfait
Beginner
3,977 Views
Sure, if you try to make a project and compile this you will get an error as described above:

module display
use picturemod
type (picture), SAVE :: pic(50), pictemp
interface assignment(=)
subroutine picture_to_picture2(outpic,inpic)
use picturemod
type (picture),intent(inout)::outpic
type (picture),intent(in)::inpic
end subroutine picture_to_picture2
end interface
end module display

module picturemod
type picture
integer nx,ny !array bounds of array coords
real*4,pointer :: array(:,:)=>Null()
end type picture
end module picturemod

subroutine picture_to_picture2(outpic,inpic)
use picturemod
implicit none
type (picture),intent(inout):: outpic
type (picture),intent(in):: inpic
write(11,*)'in pic to pic2'
end subroutine picture_to_picture2

subroutine crash()
use display
implicit none
integer i
pic(15)=pic(10)
end

program Main
use display
end

I cannot redisplay the error of pic(num)=pictemp though, because the stack exceptionoccurs at random times in my program
0 Kudos
Steven_L_Intel1
Employee
3,977 Views
You had talked about an "invalid declaration" error - can you show me that?

You may want to enable the /heap-arrays option. In Visual Studio, set it to a value of 0.
0 Kudos
jjfait
Beginner
3,977 Views
You had talked about an "invalid declaration" error - can you show me that?

You may want to enable the /heap-arrays option. In Visual Studio, set it to a value of 0.
yes, calling pic(num)=pic(num) on the first executionline of a subroutine will give the invalid declaration as the example above shows. if i add a line above it it's fine.

I can put in that option but it seems like its avoiding the real problem why there is a stack overflow when using the "=" to call an empty subroutine.
0 Kudos
Steven_L_Intel1
Employee
3,977 Views
Ok - I can see the syntax error. Looks as if the compiler thinks this is a statement function, but it isn't. I'll report it to the developers. Issue ID is DPD200140044. Adding a CONTINUE statement before the assignment is a workaround.

I don't see the stack overflow when I run this code.
0 Kudos
Steven_L_Intel1
Employee
3,977 Views
The syntax error is fixed in the compiler - I expect the fix to appear in 11.1 Update 5, scheduled for mid-February.
0 Kudos
Reply