【问题标题】:function 'free' on Haskell's FFI doesn't seem to workHaskell的FFI上的“免费”功能似乎不起作用
【发布时间】:2015-10-21 19:19:27
【问题描述】:

我正在尝试熟悉 Haskell 的 FFI,所以我写了这个小例子:

Main.hs:

{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign.C.Types
import Foreign.Ptr (Ptr)
import Foreign.Marshal.Array (peekArray)
import Foreign.Marshal.Alloc (free)

foreign import ccall "test.h test"
  test :: CInt -> Ptr CInt

main = do
  let rval = test 6

  -- print the array
  list <- peekArray 6 rval >>= return . map toInteger
  putStrLn $ show list

  free rval

  -- print it again (it should okay)
  putStrLn $ show list

  -- try to retrieve it AGAIN after I used free. Should print random values
  peekArray 6 rval >>= return . map toInteger >>= putStrLn . show

测试.h

#ifndef TEST_H
#define TEST_H

int* test(int a);

#endif

test.c

#include "test.h"
#include <stdio.h>
#include <stdlib.h>

int* test(int a)
{
    int* r_val = (int*)malloc(a * sizeof(int));
    r_val[0] = 1;
    r_val[1] = 2;
    r_val[2] = 3;
    r_val[3] = 4;
    r_val[4] = 5;
    r_val[5] = 6;
    return r_val;
}

我编译运行Main.hs时得到的输出是:

D:\Code\Haskell\Projects\Dev\TestFFI>cabal build
Building TestFFI-0.1.0.0...
Preprocessing executable 'TestFFI' for TestFFI-0.1.0.0...
[1 of 1] Compiling Main             ( src\Main.hs, dist\build\TestFFI\TestFFI-tmp\Main.o )
Linking dist\build\TestFFI\TestFFI.exe ...

D:\Code\Haskell\Projects\Dev\TestFFI>
D:\Code\Haskell\Projects\Dev\TestFFI>dist\build\TestFFI\TestFFI.exe
[1,2,3,4,5,6]
[1,2,3,4,5,6]
[1,2,3,4,5,6]

这对我来说似乎没有任何意义。我第三次打印我期待的数组:

[69128391783,2083719073,934857983457,98374293874,0239823947,2390847289347]

随机数据!

我做错了吗?我错过了什么吗?

【问题讨论】:

  • 为什么你认为释放的内存应该改变?请注意,Haskell 运行时不使用 malloc/free 来管理内存。

标签: haskell ffi


【解决方案1】:

释放内存后读取内存是未定义的行为。任何事情都是允许的——包括返回随机数据、召唤鼻恶魔,甚至在最无聊的可能世界中,返回内存中释放之前的数据。

【讨论】:

  • @TheCrafter 不,不能保证。尝试在 C 中做同样的事情。在free 之后,您可能(始终如一地!)看到相同的数据。或不。一切皆有可能。 undefined 不代表随机,它意味着运行时可以为所欲为。
  • @TheCrafter:UB 可见的可能性可能是随机的——但这可能是一个非常小的机会,所以你必须在你之前重新运行程序数百万次看到了。或者,您可以为投资者演示它,这几乎可以保证最坏的情况立即出现(例如计算机冒烟,而不是仅仅打印出随机垃圾)。
  • @TheCrafter 我没有直接回答您的问题,而是向您提出一个难题:您想象计算机在决定是输出垃圾还是输出最后写入内存时使用什么机制获得熵? (也许如果我们能理解为什么你认为计算机可以做真正随机的——而不是任意的!——事情,我们就能纠正你的这种误解。)
  • @TheCrafter 这几乎符合我对大多数现存实现中会发生什么的直觉,是的!考虑到这种期望:现代机器具有千兆字节的内存,因此期望特定的六个字节在几个周期的过程中发生变化是非常不合理的,特别是考虑到分配器通常保留“小块”内存池的方式永远不会返回给操作系统——因此较小的块不太可能被其他进程处理——以及操作系统通常重新分配内存 FIFO 样式的方式——因此最近释放的内存将需要一段时间才能重新分配。
  • @DanielWagner 好的,我明白了。但是,嘿想听一些我在帖子中没有提到的奇怪的东西吗?首先让我感到困惑的是,当我编写程序时,它实际上在第一个、第三个和第四个元素上打印了随机值。然后,几个小时后,它每次都打印正确的值。我没有提到它,因为我不想让人们相信我在编码时吸毒!
猜你喜欢
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多