Ruby C gem 运行之间的内存污染
Ruby C gem memory pollution between runs
我用 C 写了一个 gem,它似乎在运行之间保持污染的内存。
我过去曾注意到这一点,但最终发现如何通过使用 Spring 调用 RSpec 中的 Gem 来一致地重现它。当运行这个单例RSpec重启后Spring,这个例子总是通过。但是没有重新启动 Spring 的后续运行会导致垃圾数据。进一步的后续运行导致 相同 垃圾数据。
示例:
$ spring stop
Spring stopped.
$ spring rspec ..._spec.rb:122
...
1 example, 0 failures
$ spring rspec ..._spec.rb:122
...
Failures:
...
expected collection contained: [7]
actual collection contained: [1333155159]
$ spring rspec ..._spec.rb:122
...
Failures:
...
expected collection contained: [7]
actual collection contained: [1333155159]
$ spring stop
Spring stopped.
$ spring rspec ..._spec.rb:122
...
1 example, 0 failures
$ spring rspec ..._spec.rb:122
...
Failures:
...
expected collection contained: [7]
actual collection contained: [117372691]
$ spring rspec ..._spec.rb:122
...
Failures:
...
expected collection contained: [7]
actual collection contained: [117372691]
C 不应在运行之间保留任何内容。唯一的全局声明是常量、结构定义、函数和模块名称本身。例如(简化为每种类型的声明中只有一个,headers 除外):
#include <ruby.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define SOME_CONSTANTS 100
struct some_structs {
long id;
double amount;
};
static long some_functions();
VALUE MyModuleName = Qnil;
VALUE internal_function_name(VALUE self, VALUE rb_data, VALUE rb_options);
void Init_my_gem() {
MyModuleName = rb_define_module("MyModuleName");
rb_define_singleton_method(MyModuleName, "exposed_function_name",
internal_function_name, 2);
}
感谢您对正在发生的事情的任何想法。
编辑
我把它隔离到这个:
printf("A orders[0].products[0]->id: %lu\n", orders[0].products[0]->id);
VALUE rb_best_orders = rb_ary_new();
printf("B orders[0].products[0]->id: %lu\n", orders[0].products[0]->id);
Output:
A orders[0].products[0]->id: 7
B orders[0].products[0]->id: 140735021913496
注意 orders 被定义为 struct order *orders;
,它的内存是通过 malloc 获取的。
已使用 ALLOC_N
而不是 malloc
修复。 http://clalance.blogspot.com/2011/01/writing-ruby-extensions-in-c-part-12.html 很有帮助,尽管它说 malloc 应该可以工作。
我用 C 写了一个 gem,它似乎在运行之间保持污染的内存。
我过去曾注意到这一点,但最终发现如何通过使用 Spring 调用 RSpec 中的 Gem 来一致地重现它。当运行这个单例RSpec重启后Spring,这个例子总是通过。但是没有重新启动 Spring 的后续运行会导致垃圾数据。进一步的后续运行导致 相同 垃圾数据。
示例:
$ spring stop
Spring stopped.
$ spring rspec ..._spec.rb:122
...
1 example, 0 failures
$ spring rspec ..._spec.rb:122
...
Failures:
...
expected collection contained: [7]
actual collection contained: [1333155159]
$ spring rspec ..._spec.rb:122
...
Failures:
...
expected collection contained: [7]
actual collection contained: [1333155159]
$ spring stop
Spring stopped.
$ spring rspec ..._spec.rb:122
...
1 example, 0 failures
$ spring rspec ..._spec.rb:122
...
Failures:
...
expected collection contained: [7]
actual collection contained: [117372691]
$ spring rspec ..._spec.rb:122
...
Failures:
...
expected collection contained: [7]
actual collection contained: [117372691]
C 不应在运行之间保留任何内容。唯一的全局声明是常量、结构定义、函数和模块名称本身。例如(简化为每种类型的声明中只有一个,headers 除外):
#include <ruby.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define SOME_CONSTANTS 100
struct some_structs {
long id;
double amount;
};
static long some_functions();
VALUE MyModuleName = Qnil;
VALUE internal_function_name(VALUE self, VALUE rb_data, VALUE rb_options);
void Init_my_gem() {
MyModuleName = rb_define_module("MyModuleName");
rb_define_singleton_method(MyModuleName, "exposed_function_name",
internal_function_name, 2);
}
感谢您对正在发生的事情的任何想法。
编辑
我把它隔离到这个:
printf("A orders[0].products[0]->id: %lu\n", orders[0].products[0]->id);
VALUE rb_best_orders = rb_ary_new();
printf("B orders[0].products[0]->id: %lu\n", orders[0].products[0]->id);
Output:
A orders[0].products[0]->id: 7
B orders[0].products[0]->id: 140735021913496
注意 orders 被定义为 struct order *orders;
,它的内存是通过 malloc 获取的。
已使用 ALLOC_N
而不是 malloc
修复。 http://clalance.blogspot.com/2011/01/writing-ruby-extensions-in-c-part-12.html 很有帮助,尽管它说 malloc 应该可以工作。