2011-04-05 26 views
2

我正在爲Ruby模塊構建一個簡單的C擴展,當我在擴展中調用另一個C函數時,遇到了段錯誤。執行的基本流程是這樣的:Ruby 1.8.7:C擴展中調用函數的Segfault

  1. 我創建Ruby類,並調用它的一個實例方法,它
  2. 調用C方法在我的擴展,它
  3. 調用另一個C函數,在一個單獨的文件,但編譯好吧

這是最後一次跳躍似乎打破。我已經能夠重現幾乎沒有功能的問題,但函數調用。我有一個標準的extconf.rb,用make編譯這個東西,並且它在encrypt()的調用中發生了段錯誤。上運行,我發出以下命令:

$ ruby extconf.rb 
$ make clean 
$ make 
$ ruby -r des -e 'puts DES.new.encrypt!'

輸出:

creating Makefile 
/usr/bin/gcc-4.2 -I. -I/opt/local/lib/ruby/1.8/i686-darwin10 -I/opt/local/lib/ruby/1.8/i686-darwin10 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -fno-common -std=c99 -arch x86_64 -c calc.c 
/usr/bin/gcc-4.2 -I. -I/opt/local/lib/ruby/1.8/i686-darwin10 -I/opt/local/lib/ruby/1.8/i686-darwin10 -I. -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -fno-common -std=c99 -arch x86_64 -c deslib.c 
/usr/bin/gcc-4.2 -dynamic -bundle -undefined suppress -flat_namespace -o calc.bundle calc.o deslib.o -L. -L/opt/local/lib -L/opt/local/lib -L. -L/opt/local/lib -arch x86_64 -arch x86_64 -lruby -lpthread -ldl -lobjc 
About to do C encrypt... 
./des.rb:42: [BUG] Segmentation fault 
ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-darwin10] 

zsh: abort  ruby -r des -e 'puts DES.new.encrypt!'

的Ruby類:

class D 
    def encrypt! 
     self.encrypted = Calc.encrypt(0,0,0) 
     return self.encrypted 
    end 
end

的計算器模塊:

#include "ruby.h" 
#include "cryptlib.h" 

VALUE Calc = Qnil; 
void Init_calc(); 

VALUE method_encrypt(VALUE self, VALUE m, VALUE k, VALUE n); 

void Init_calc() { 
    Calc = rb_define_module("Calc"); 
    rb_define_method(Calc, "encrypt", method_encrypt, 3); 
} 

VALUE method_encrypt(VALUE self, VALUE m, VALUE k, VALUE n) { 
    uint64_t message = NUM2ULONG(m); 
    uint64_t key = NUM2ULONG(k); 
    int iters = NUM2INT(n); 

    printf("About to do C encrypt...\n"); 
    uint64_t ciphertext = encrypt(message, key, iters); 
    printf("Done with C encrypt\n"); 

    return ULONG2NUM(ciphertext); 
} 

cryptlib。 h:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <string.h> 

uint64_t encrypt(uint64_t message, uint64_t key, int iters);

cryptlib.c:

#include "cryptlib.h" 

uint64_t encrypt(uint64_t message, uint64_t key, int iters) { 
    return 0; 
}

爲什麼這個破得厲害?我在MacBook Pro上運行ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-darwin10],MacPorts在不到一小時前編譯完成。我gcc --versioni686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)

回答

0

原來,encrypt功能名稱中較高保留了在Ruby的C擴展庫。將函數重命名並且一切正常。