问题描述
我正在编写一个 C 库的接口。 C 函数分配一些内存,读取一个值,并返回一个指向该缓冲区的 void *
指针,随后将被释放。
我希望确保当我将 nativecast(Str,$data)
调用的输出分配给 Raku Str 变量时,数据被分配给变量(复制到),而不仅仅是绑定到它,所以我可以释放空间赋值后不久由 C 函数分配。
代码大致如下:
my Pointer $data = c_read($source);
my Str $value = nativecast(Str,$data);
c_free($data);
# $value is now ready to be used
我通过 valgrind 运行此代码,它没有报告任何尝试引用已释放的内存缓冲区的情况。我还是很好奇。
解决方法
Str
的内部结构与 C 字符串完全不兼容。所以它们在使用之前必须被解码。
更具体地说,如果没有 NFC 代码点,MoarVM 会将字形集群存储为 [否定] 合成代码点。这意味着即使是同一个程序的两个实例也可能对同一个字素簇使用不同的合成码点。
即使忽略这一点,MoarVM 也将字符串存储为不可变的数据结构。这意味着它不能只使用 C 字符串,因为 C 代码可能会在 MoarVM 下改变它,打破这个假设。
我确定它不能按原样使用 C 字符串的原因还有很多。
就像我说的,Str
的内部结构与 C 字符串完全不兼容。因此,它继续使用 C 函数分配的空间的可能性为零。
这里最大的问题是在释放缓冲区后调用 nativecast
。