C ++分配的内存的Fortran释放

时间:2018-09-18 17:51:36

标签: c++ c++11 fortran fortran-iso-c-binding

要放置一些背景上下文,我需要一个线程安全随机数生成器,以用于需要跨编译器和跨平台兼容的多线程Fortran代码。实现此目标的最佳方法是遵守语言标准。因此,我想将C ++ 11随机数生成器包装在一个可以从fortran中调用的函数中,以便每个线程有一个随机数生成器,每个线程都有它自己的状态对象。

所以我创建了一个带有3个C函数绑定的小型C ++类。

#include <random>
#include <iostream>

class random {
    std::mt19937_64 engine;
    std::uniform_real_distribution<double> dist;

    public:
    random(uint64_t seed) : engine(seed), dist(0.0, 1.0) {};
    double get_number() {
        return dist(engine);
    }
};

extern "C" {
    void *random_construct(int seed) {
        return new class random(static_cast<uint64_t> (seed));
    }

    double random_get_number(void *r) {
        return static_cast<class random *> (r)->get_number();
    }

    void random_destroy(void *r) {
        delete static_cast<class random *> (r);
    }
}

Fortran界面

  MODULE random
  USE, INTRINSIC :: iso_c_binding

  IMPLICIT NONE

  INTERFACE
     TYPE (C_PTR) FUNCTION random_construct(seed)                          &
 &   BIND(C, NAME='random_construct')
     USE, INTRINSIC :: iso_c_binding

     IMPLICIT NONE

     INTEGER (C_INT), VALUE :: seed

     END FUNCTION
  END INTERFACE

  INTERFACE
     REAL (C_DOUBLE) FUNCTION random_get_number(r)                         &
 &   BIND(C, NAME='random_get_number')
     USE, INTRINSIC :: iso_c_binding

     IMPLICIT NONE

     TYPE (C_PTR), VALUE :: r

     END FUNCTION
  END INTERFACE

  INTERFACE
     SUBROUTINE random_destroy(r)                                          &
 &   BIND(C, NAME='random_destroy')
     USE, INTRINSIC :: iso_c_binding

     IMPLICIT NONE

     TYPE (C_PTR), VALUE :: r

     END SUBROUTINE
  END INTERFACE

  END MODULE

还有一个小程序对此进行测试。

   PROGRAM random_test
   USE random

   IMPLICIT NONE

   TYPE (C_PTR) :: rand_object
   INTEGER      :: count

   CALL SYSTEM_CLOCK(count)
   rand_object = random_construct(count)

   WRITE(*,*) random_get_number(rand_object)

   CALL random_destroy(rand_object)

   WRITE(*,*) random_get_number(rand_object)  ! Expected to segfault.

   END PROGRAM

运行此命令表明我的销毁功能似乎无法正常工作,因为我的销毁功能之后的调用仍在生成随机数。

如果我将测试程序更改为

   PROGRAM random_test
   USE random

   IMPLICIT NONE

   TYPE (C_PTR), ALLOCATABLE :: rand_object
   INTEGER                   :: count

   CALL SYSTEM_CLOCK(count)
   rand_object = random_construct(count)

   WRITE(*,*) random_get_number(rand_object)

   DEALLOCATE (rand_object)

   WRITE(*,*) random_get_number(rand_object)

   END PROGRAM

现在,它会产生我预期的行为,并且在DEALLOCATE之后会出现段错误。现在我的直觉反应说这应该行不通,因为我永远不会尝试用一种语言分配内存,而用另一种语言取消分配内存。但是,有什么理由不应该这样做吗? C ++对象是POD类型,因此其内存应该是连续的。然后,只要Fortran具有正确的内存地址,它就可以轻松地对其进行分配。这里有我想念的东西吗?

0 个答案:

没有答案