【发布时间】:2020-11-14 13:48:12
【问题描述】:
我正在编写一个 Ruby C 扩展,需要调用 rb_raise() 并将其传递给 char *。我还需要释放给定的char *。我当前的行为不会释放任何东西,而我尝试过的另一种方法导致我陷入未定义的行为。这样做的正确方法是什么?
这是我的问题的一个最小示例:
static VALUE
rb_some_function(VALUE self)
{
char *foo;
foo = malloc(100);
strcpy(foo, "message\0");
rb_raise(rb_eRuntimeError, "%s\n", foo);
free(foo); // This won't work since rb_raise exits the function using longjmp()
}
我的想法是在rb_raise 之前发送free。我用一个小程序试过这个,检查它是否会导致任何泄漏:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void stuff(int i)
{
char *str;
str = malloc(100);
strcpy(str, "message\0");
free(str); // this feel very wrong to free and then use
printf("\r%s %i", str, i);
}
int main(int argc, char const *argv[])
{
// Time for instrument to attach.
sleep(5);
for (int i = 0; i < 1e6; i++) stuff(i);
printf("\n");
return 0;
}
这似乎是安全的,不会泄漏。但是在使用前释放让我认为这会导致我不知道的麻烦。就像this answer 中建议的未定义行为。
你知道rb_raise和free包含错误信息的字符串的安全方式吗?
【问题讨论】:
-
'这不起作用,因为 rb_raise'......rb_raise() 坏了,修复它。
-
@Martin James,rb_raise 是 ruby 核心 API 的 psrt。我几乎不相信它已经坏了,无论如何也无法改变它。它在内部使用 longjmp。无论如何,不幸的是,修复 rb_raise 不是一个可接受的解决方案。如果您是反对者,请告诉我如何改进我的问题。我已经链接了 rb_raise 参考。
-
好的,那么你调用/使用 rb_raise() 的方式就很糟糕了。释放空间然后访问它是 100% 错误的,并且用未定义的行为掩盖了问题的根本原因。
-
好的,感谢您消除对此的怀疑。但是问题仍然存在,我该如何使用该功能并释放内存。也许这对于了解 ruby C API 的人来说是一个问题,我也在澄清介绍
-
使用静态数组而不是分配内存,也许吧?
标签: c ruby ruby-c-extension