The following code compiles in both GNU gfortran and Intel ifort. But only the gfortran compiled version will run successfully.
program fort_tst
use iso_c_binding
INTEGER, POINTER :: a(:)
TYPE(C_PTR) :: ptr
INTEGER, POINTER :: b(:)
ALLOCATE(a(5))
ptr = c_loc(a)
CALL c_f_pointer(ptr,b,[5])
DEALLOCATE(b)
end program fort_tst
The error in the Intel compiled code is :
forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Image PC Routine Line Source
fort_tst 000000000040C5A1 Unknown Unknown Unknown
fort_tst 0000000000403A17 Unknown Unknown Unknown
fort_tst 0000000000403812 Unknown Unknown Unknown
libc-2.17.so 00002AAAAB20F555 __libc_start_main Unknown Unknown
fort_tst 0000000000403729 Unknown Unknown Unknown
The gfortran code runs to completion. A quick valgrind check does not find any leaks.
Can someone confirm whether the code above is valid/legal code?
I am running
ifort (IFORT) 2021.2.0 20210228
and
GNU Fortran (GCC) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.
UPDATE :
What is interesting is that gfortran does the right thing, (i.e. deallocates only allocated memory), even when the user tries to confound it with improper index remapping, or a bogus shape argument. So the internal array descriptor is being properly copied over with gfortran's c_f_pointer.
The error is issued, because the compiler claims that the pointer that is being allocated was not allocated by an allocate statement.
The rules are (F2018):
9.7.3.3 Deallocation of pointer targets
1 If a pointer appears in a DEALLOCATE statement, its association status shall be defined.
Deallocating a pointer that is disassociated or whose target was not
created by an ALLOCATE statement causes an error condition in the
DEALLOCATE statement. If a pointer is associated with an allocatable
entity, the pointer shall not be deallocated. A pointer shall not be
deallocated if its target or any subobject thereof is argument
associated with a dummy argument or construct associated with an
associate name.
Your pointer b was associated using the c_f_pointer subroutine. The error condition mentioned is the
forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Now we have to be careful, the exact wording is
or whose target was not created by an ALLOCATE statement
The target arguably was created by an allocatable statement. And then went through this indirect chain of association. I am not such an expert language lawyer to be sure whether this makes the target to be applicable or not, when it passed through c_loc() and c_f_pointer().
Gfortran does not issue this error condition and then it works fine because at the end of the day, under the hood, what matters is that the address passed to the system free() function was allocated by the matching system malloc() function.
I think we can conclude that one of the compilers is wrong here, because the mention of the error condition is clear in the standard and either it should be issued or it should not. A third option, that gfortran just leaves it too work, should not happen. Either it is allowed, or an error condition shall be issued.
Re UPDATE: What gfortran does is really sending the address to free(). As long as the pointer is contiguous and starts at the first element, it will work in practice. The size is not necessary and is not passed to free(). The system allocator malloc()/free() stores the size of each allocated system in its own database.
There are even worse abuse cases that can happen and will work just by chance due to this, even if completely illegal in Fortran.
See this:
use iso_c_binding
character, allocatable, target :: a
type(c_ptr) :: p
real, pointer :: b(:)
allocate(a)
p = c_loc(a)
call c_f_pointer(p, b, [1000])
deallocate(b)
end
gfortran is arguably missing a diagnostics opportunity when it comes to the DEALLOCATE statement. ifort is arguably too conservative when it comes to the DEALLOCATE statement.
The error message from ifort is an explicit design choice prohibiting the pointer from C_F_POINTER appearing in a DEALLOCATE statement:
Since the resulting data pointer fptr could point to a target that was not allocated with an ALLOCATE statement, fptr cannot be freed with a DEALLOCATE statement.
There seems little in Fortran 2018 explicitly to support that restriction (even in the case where the target was created by an ALLOCATE statement), and ifort itself isn't consistent in applying it:
use iso_c_binding
integer, pointer :: a, b
type(c_ptr) :: ptr
allocate(a)
ptr = c_loc(a)
call c_f_pointer(ptr,b)
deallocate(b)
end program
However, consider the case
use iso_c_binding
integer, pointer, dimension(:) :: a, b
type(c_ptr) :: ptr
allocate(a(5))
ptr = c_loc(a)
call c_f_pointer(ptr,b,[4])
deallocate(b)
end program
One would surely expect deallocation here to be problematic but this doesn't cause an error condition with gfortran: gfortran isn't carefully checking whether the target is deallocatable (note that it doesn't have to).
There is some subtlety in Fortran 2018's wording of C_F_POINTER (F2018 18.2.3.3)
If both X and FPTR are arrays, SHAPE shall specify a size that is less than or equal to the size of X, and FPTR becomes associated with the first PRODUCT (SHAPE) elements of X (this could be the entirety of X).
and whether "the entirety" of a forms a valid thing to deallocate but ifort's documentation is seemingly too strict and gfortran's checking is not going to catch all invalid cases. There is a case for talking to the vendor of each compiler.
That said, the use of a C_F_POINTER's pointer in a DEALLOCATE statement clearly is more prone to error than "simpler" pointers, and these errors are not ones where we can rely on a compiler to point them out. Even with a conclusion of "clearly this is allowed" I personally would recommend that one avoids this approach where possible without other bad things.
Usage of c_f_pointer is pretty standard behavior in case a Fortran derived type is to be passed to a C++ class as an opaque pointer type, see e.g. the following interoperable class:
module mytype_m
use iso_c_binding
implicit none
private
type, public :: mytype
real, allocatable :: data(:)
contains
procedure :: destroy
procedure :: init
procedure :: printout
end type mytype
public :: mytype_print_c
public :: mytype_init_c
public :: mytype_destroy_c
contains
subroutine init(this,data)
class(mytype), intent(inout), target :: this
real, intent(in) :: data(:)
call destroy(this)
this%data = data
end subroutine init
elemental subroutine destroy(this)
class(mytype), intent(inout), target :: this
integer :: ierr
deallocate(this%data,stat=ierr)
end subroutine destroy
subroutine printout(this)
class(mytype), intent(inout), target :: this
integer :: ndata,i
ndata = merge(size(this%data),0,allocated(this%data))
write(*,1) ndata,(this%data(i),i=1,ndata)
1 format('mytype object has data(',i0,')',:,' = ',*(f3.1,:,', '))
end subroutine printout
subroutine mytype_print_c(this) bind(C,name='mytype_print_c')
type(c_ptr), intent(inout) :: this
type(mytype), pointer :: fortranclass
call c_f_pointer(this, fortranclass)
call fortranclass%printout()
end subroutine mytype_print_c
subroutine mytype_destroy_c(this) bind(C,name='mytype_destroy_c')
type(c_ptr), intent(inout) :: this
type(mytype), pointer :: fortranclass
call c_f_pointer(this, fortranclass)
if (associated(fortranclass)) then
call fortranclass%destroy()
deallocate(fortranclass)
end if
! Nullify C pointer
this = c_null_ptr
end subroutine mytype_destroy_c
subroutine mytype_init_c(this,ndata,data) bind(C,name='mytype_init_c')
type(c_ptr), intent(inout) :: this
integer(c_int), intent(in), value :: ndata
real(c_float), intent(in) :: data(ndata)
type(mytype), pointer :: fortranclass
integer :: ierr
! In case it was previously allocated
call c_f_pointer(this, fortranclass)
allocate(fortranclass,stat=ierr)
call fortranclass%init(data)
this = c_loc(fortranclass)
end subroutine mytype_init_c
end module mytype_m
that would be bound to an opaque pointer in c++:
#include <iostream>
#include <vector>
using namespace std;
// Fortran interoperability
typedef void* mytype;
extern "C" { void mytype_print_c(mytype self);
void mytype_destroy_c(mytype self);
void mytype_init_c(mytype self, const int ndata, float *data); }
// Class definition
class mytype_cpp
{
public:
mytype_cpp(std::vector<float> data) { mytype_init_c(this,data.size(),data.data()); };
~mytype_cpp() { mytype_destroy_c(this); };
void printout() { mytype_print_c(this); };
};
int main()
{
// Print 8--size
std::vector<float> data {1.,2.,3.,4.,5.,6.,7.,8.};
mytype_cpp obj(data); obj.printout();
return 0;
}
which, with gfortran-10, returns
mytype object has data(8) = 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0
I don't have a chance to test with ifort, but it works seamlessly with gcc, how can this approach not be Fortran standard-compliant?
Posts above inspired the following solution. The idea is to create a type that wraps the actual data array. Then, c_loc/c_f_pointer sequence works fine with a pointer to a scalar object. The data array stored in the type can be safely allocated, along with the array type itself.
MODULE arraytype_m
TYPE, PUBLIC :: arraytype
INTEGER, ALLOCATABLE :: data(:)
END TYPE arraytype
END MODULE arraytype_m
PROGRAM fort_tst
USE iso_c_binding
USE arraytype_m
TYPE(arraytype), POINTER :: a, b
TYPE(C_PTR) :: ptr
ALLOCATE(a)
ALLOCATE(a%data(5))
!! Set to C-style pointer, and then copy back to Fortran pointer.
ptr = c_loc(a)
CALL c_f_pointer(ptr,b)
DEALLOCATE(b%data)
DEALLOCATE(b)
END PROGRAM fort_tst
This works with both Intel and gfortan, and is really a better solution than what I was trying to do.
Special thanks for #Federico for posting the C++/Fortran code that made this solution obvious.
Update : A complete code, which shows how the ptr above can be stored in C.
// C code
typedef void* arraytype;
void allocate_array(arraytype *ptr);
void deallocate_array(arraytype *ptr);
void do_something(arraytype *ptr);
int main()
{
arraytype ptr;
allocate_array(&ptr);
do_something(&ptr);
deallocate_array(&ptr);
return 0;
}
and the corresponding Fortran :
!! Fortran code
MODULE arraytype_mod
TYPE, PUBLIC :: arraytype
DOUBLE PRECISION, POINTER :: data(:)
END TYPE arraytype
END MODULE arraytype_mod
SUBROUTINE allocate_array(ptr) BIND(C,name='allocate_array')
USE iso_c_binding
USE arraytype_mod
TYPE(c_ptr) :: ptr
TYPE(arraytype), POINTER :: a
ALLOCATE(a)
ALLOCATE(a%data(5))
ptr = c_loc(a)
END
SUBROUTINE deallocate_array(ptr) BIND(C,name='deallocate_array')
USE iso_c_binding
USE arraytype_mod
TYPE(C_PTR) :: ptr
TYPE(arraytype), pointer :: a
CALL c_f_pointer(ptr,a)
DEALLOCATE(a%data)
DEALLOCATE(a)
END
SUBROUTINE do_something(ptr) BIND(C,name='do_something')
USE iso_c_binding
USE arraytype_mod
TYPE(c_ptr) :: ptr
TYPE(arraytype), POINTER :: a
CALL c_f_pointer(ptr,a)
a%data = 2.5
WRITE(6,*) a%data
END
The following code works:
type Brace interface {}
type Round struct {
prev_ Brace
}
type Square struct {}
func main() {
var r Round
var s Square
r.prev_ = s
}
Is it true that r.prev_ is now a copy of s? How can I change it that Round will contain a pointer to Brace? This code doesn't work:
type Brace interface {}
type Round struct {
prev_ *Brace
}
type Square struct {}
func main() {
var r Round
var s Square
r.prev_ = &s
}
because of the error:
cannot use &s (type *Square) as type *Brace in assignment:
*Brace is pointer to interface, not interface
As the error says:
cannot use &s (type *Square) as type *Brace in assignment: *Brace is
pointer to interface, not interface
An interface can wrap any type of value. But you are wraping the struct inside pointer type interface not an interface. That's not how interface works in golang.
If you wants to pass the address of an struct. An interface can wrap the pointer to struct directly. There is no need of creating a pointer to an interface to achieve that.
type Brace interface {}
type Round struct {
prev_ Brace
}
type Square struct {}
func main() {
var r Round
var s Square
r.prev_ = &s
fmt.Printf("%#v", r)
}
Playground Example
In Golang you should avoid passing a pointer to interface as:
The compiler will complain about this error but the situation can
still be confusing, because sometimes a pointer is necessary to
satisfy an interface. The insight is that although a pointer to a
concrete type can satisfy an interface, with one exception a pointer
to an interface can never satisfy an interface.
Consider the variable declaration,
var w io.Writer
The printing function fmt.Fprintf takes as its first argument a value that satisfies io.Writer—something that implements the canonical Write method. Thus we can write
fmt.Fprintf(w, "hello, world\n")
If however we pass the address of w, the program will not compile.
fmt.Fprintf(&w, "hello, world\n") // Compile-time error.
The one exception is that any value, even a pointer to an interface,
can be assigned to a variable of empty interface type (interface{}).
Even so, it's almost certainly a mistake if the value is a pointer to
an interface; the result can be confusing.
Check it on Go playground. You will find the same error you are getting in your code snippet when trying to pass pointer to interface.
According to this response to this question
The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers
But in fact I can execute pointer method on non pointer values:
package main
import "fmt"
type car struct {
wheels int
}
func (c *car) fourWheels() {
c.wheels = 4
}
func main() {
var c = car{}
fmt.Println("Wheels:", c.wheels)
c.fourWheels()
// Here i can execute pointer method on non pointer value
fmt.Println("Wheels:", c.wheels)
}
So, what is wrong here? Is this a new feature ? or the response to the question is wrong ?
You are calling a "pointer method" on a pointer value. In the expression:
c.fourWheels()
c is of type car (non-pointer); since the car.fourWheels() method has a pointer receiver and because the receiver value is a non-pointer and is addressable, it is a shorthand for:
(&c).fourWheels()
This is in Spec: Calls:
If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().
The statement:
The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers
Interpret it like this:
If you have a value method, you can always call it: if you have a value, it's ready to be the receiver; and if you have a pointer, you can always dereference it to obtain a value ready to be the receiver.
If you have a pointer method, you may not always be able to call it if you only have a value, as there are several expressions (whose result) are not addressable, and therefore you would not be able to obtain a pointer to it that would be used as the receiver; such examples are function return values and map indexing expressions. For details and examples, see How can I store reference to the result of an operation in Go?; and How to get the pointer of return value from function call? (Sure, you could always assign it to a local variable and take its address, but that's a copy and the pointer method could only modify this copy and not the original.)
I am using reflection for a library I'm building but there's something I don't understand about reflect.New.
type A struct {
A int
B string
}
func main() {
real := new(A)
reflected := reflect.New(reflect.TypeOf(real)).Elem().Interface()
fmt.Println(real)
fmt.Println(reflected)
}
Gives:
$ go run *go
&{0 }
<nil>
Isn't reflect.New supposed to return &{0 } too? (Runnable Version)
Ultimately, I wish to be able to iterate over the fields of the reflected struct (reflected.NumField() gives reflected.NumField undefined (type interface {} is interface with no methods)) and use SetInt, SetString and so on.
Thanks,
You used the builtin new() function when you created your real variable, which returns a pointer! Type of real is *A, not A! This is the source of the confusion.
reflect.New() returns a pointer to the (zeroed) value of the given type (wrapped in a reflect.Value). If you pass the type A, you get back a wrapped *A, A initialized / zeroed. If you pass the type *A, you get back a wrapped **A, *A initialized (zeroed), and the zero value for any pointer type is nil.
You basically ask reflect.New() to create a new value of a pointer type (*A), and –as mentioned– its zero value is nil.
You have to pass the type A (and not the type *A). It works like this (try it on the Go Playground):
real := new(A)
reflected := reflect.New(reflect.TypeOf(real).Elem()).Elem().Interface()
fmt.Println(real)
fmt.Println(reflected)
Or like this (Go Playground):
real := A{}
reflected := reflect.New(reflect.TypeOf(real)).Elem().Interface()
fmt.Println(real)
fmt.Println(reflected)
There are already several Q&As on this "X does not implement Y (... method has a pointer receiver)" thing, but to me, they seems to be talking about different things, and not applying to my specific case.
So, instead of making the question very specific, I'm making it broad and abstract -- Seems like there are several different cases that can make this error happen, can someone summary it up please?
I.e., how to avoid the problem, and if it occurs, what are the possibilities? Thx.
This compile-time error arises when you try to assign or pass (or convert) a concrete type to an interface type; and the type itself does not implement the interface, only a pointer to the type.
Short summary: An assignment to a variable of interface type is valid if the value being assigned implements the interface it is assigned to. It implements it if its method set is a superset of the interface. The method set of pointer types includes methods with both pointer and non-pointer receiver. The method set of non-pointer types only includes methods with non-pointer receiver.
Let's see an example:
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
The Stringer interface type has one method only: String(). Any value that is stored in an interface value Stringer must have this method. We also created a MyType, and we created a method MyType.String() with pointer receiver. This means the String() method is in the method set of the *MyType type, but not in that of MyType.
When we attempt to assign a value of MyType to a variable of type Stringer, we get the error in question:
m := MyType{value: "something"}
var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
// MyType does not implement Stringer (String method has pointer receiver)
But everything is ok if we try to assign a value of type *MyType to Stringer:
s = &m
fmt.Println(s)
And we get the expected outcome (try it on the Go Playground):
something
So the requirements to get this compile-time error:
A value of non-pointer concrete type being assigned (or passed or converted)
An interface type being assigned to (or passed to, or converted to)
The concrete type has the required method of the interface, but with a pointer receiver
Possibilities to resolve the issue:
A pointer to the value must be used, whose method set will include the method with the pointer receiver
Or the receiver type must be changed to non-pointer, so the method set of the non-pointer concrete type will also contain the method (and thus satisfy the interface). This may or may not be viable, as if the method has to modify the value, a non-pointer receiver is not an option.
Structs and embedding
When using structs and embedding, often it's not "you" that implement an interface (provide a method implementation), but a type you embed in your struct. Like in this example:
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2 // Compile-time error again
Again, compile-time error, because the method set of MyType2 does not contain the String() method of the embedded MyType, only the method set of *MyType2, so the following works (try it on the Go Playground):
var s Stringer
s = &m2
We can also make it work, if we embed *MyType and using only a non-pointer MyType2 (try it on the Go Playground):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
Also, whatever we embed (either MyType or *MyType), if we use a pointer *MyType2, it will always work (try it on the Go Playground):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
Relevant section from the spec (from section Struct types):
Given a struct type S and a type named T, promoted methods are included in the method set of the struct as follows:
If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
So in other words: if we embed a non-pointer type, the method set of the non-pointer embedder only gets the methods with non-pointer receivers (from the embedded type).
If we embed a pointer type, the method set of the non-pointer embedder gets methods with both pointer and non-pointer receivers (from the embedded type).
If we use a pointer value to the embedder, regardless of whether the embedded type is pointer or not, the method set of the pointer to the embedder always gets methods with both the pointer and non-pointer receivers (from the embedded type).
Note:
There is a very similar case, namely when you have an interface value which wraps a value of MyType, and you try to type assert another interface value from it, Stringer. In this case the assertion will not hold for the reasons described above, but we get a slightly different runtime-error:
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
Runtime panic (try it on the Go Playground):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
Attempting to convert instead of type assert, we get the compile-time error we're talking about:
m := MyType{value: "something"}
fmt.Println(Stringer(m))
To keep it short and simple, let say you have a Loader interface and a WebLoader that implements this interface.
package main
import "fmt"
// Loader defines a content loader
type Loader interface {
load(src string) string
}
// WebLoader is a web content loader
type WebLoader struct{}
// load loads the content of a page
func (w *WebLoader) load(src string) string {
return fmt.Sprintf("I loaded this page %s", src)
}
func main() {
webLoader := WebLoader{}
loadContent(webLoader)
}
func loadContent(loader Loader) {
loader.load("google.com")
}
The above code will give you this compile time error
./main.go:20:13: cannot use webLoader (type WebLoader) as type Loader
in argument to loadContent:
WebLoader does not implement Loader (Load method has pointer receiver)
To fix it you only need to change webLoader := WebLoader{} to following:
webLoader := &WebLoader{}
Why this will fix the issue? Because you defined this function func (w *WebLoader) Load to accept a pointer receiver. For more explanation please read #icza and #karora answers
Another case when I have seen this kind of thing happening is if I want to create an interface where some methods will modify an internal value and others will not.
type GetterSetter interface {
GetVal() int
SetVal(x int) int
}
Something that then implements this interface could be like:
type MyTypeA struct {
a int
}
func (m MyTypeA) GetVal() int {
return a
}
func (m *MyTypeA) SetVal(newVal int) int {
int oldVal = m.a
m.a = newVal
return oldVal
}
So the implementing type will likely have some methods which are pointer receivers and some which are not and since I have quite a variety of these various things that are GetterSetters I'd like to check in my tests that they are all doing the expected.
If I were to do something like this:
myTypeInstance := MyType{ 7 }
... maybe some code doing other stuff ...
var f interface{} = myTypeInstance
_, ok := f.(GetterSetter)
if !ok {
t.Fail()
}
Then I won't get the aforementioned "X does not implement Y (Z method has pointer receiver)" error (since it is a compile-time error) but I will have a bad day chasing down exactly why my test is failing...
Instead I have to make sure I do the type check using a pointer, such as:
var f interface{} = new(&MyTypeA)
...
Or:
myTypeInstance := MyType{ 7 }
var f interface{} = &myTypeInstance
...
Then all is happy with the tests!
But wait! In my code, perhaps I have methods which accept a GetterSetter somewhere:
func SomeStuff(g GetterSetter, x int) int {
if x > 10 {
return g.GetVal() + 1
}
return g.GetVal()
}
If I call these methods from inside another type method, this will generate the error:
func (m MyTypeA) OtherThing(x int) {
SomeStuff(m, x)
}
Either of the following calls will work:
func (m *MyTypeA) OtherThing(x int) {
SomeStuff(m, x)
}
func (m MyTypeA) OtherThing(x int) {
SomeStuff(&m, x)
}
Extend from above answers (Thanks for all of your answers)
I think it would be more instinctive to show all the methods of pointer / non pointer struct.
Here is the playground code.
https://play.golang.org/p/jkYrqF4KyIf
To summarize all the example.
Pointer struct type would include all non pointer / pointer receiver methods
Non pointer struct type would only include non pointer receiver methods.
For embedded struct
non pointer outer struct + non pointer embedded struct => only non pointer receiver methods.
non pointer outer struct + pointer embedded struct / pointer outer struct + non pointer embedded struct / pointer outer struct + pointer embedded struct => all embedded methods