簡體   English   中英

在ruby上調用c函數時出現分段錯誤

[英]segmentation fault when calling c function on ruby

我正在嘗試使用C函數擴展我的Ruby代碼。 C代碼編譯時沒有警告。 但是,當我嘗試運行ruby代碼時,出現了段錯誤:

我有這個C代碼:

#include <ruby.h>

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

#include "nessie.h"

/* #define TRACE_INTERMEDIATE_VALUES */

/*
 * The number of rounds of the internal dedicated block cipher.
 */
#define R 10

VALUE rb_mExample;
VALUE rb_cClass;

// ...

static char* displayHash(const unsigned char array[], int length){
  int i, k;
  char *str;

  str = malloc(3 * length + 1);
  if (str == NULL) {
    return NULL;
  }

  k = 0;
  str[0] = '\0';
  for (i = 0; i < length; i++){
    char hex[3];

    if (i % 32 == 0){
      str[k++] = ' ';
    }

    if (i % 8 == 0){
      str[k++] = ' ';
    }
    snprintf(hex, sizeof(hex), "%02X", array[i]);

    str[k++] = hex[0];
    str[k++] = hex[1];
  }

  str[k] = '\0';

  return str;
}


VALUE
print_string(VALUE class, VALUE *valor) {
  struct NESSIEstruct w;
  u8 digest[DIGESTBYTES];

  int i;
  for (i = 0; valor[i] != '\0'; i++);
  int sizeo = i;

  NESSIEinit(&w);
  NESSIEadd((u8*)valor, 8*sizeo, &w);
  NESSIEfinalize(&w, digest);

  return (VALUE) displayHash(digest, DIGESTBYTES);
}

void
Init_example(){
  rb_mExample = rb_define_module("Example");
  rb_cClass = rb_define_class_under(rb_mExample, "Class", rb_cObject);

  rb_define_method(rb_cClass, "print_string", print_string, 1);
}

以及以下Ruby代碼:

require "example"

def print
  e = Example::Class.new
  e.print_string("ruby")
end

當我運行ruby代碼時,出現了分段錯誤。

編輯:要點與日志信息

https://gist.github.com/psantos10/f07484afa26ce0e55181

我哪里失敗了? 我是C語言新手。

編輯:

我將“ print_string”更改為如下形式:

VALUE
print_string(VALUE class, VALUE *valor) {
  struct NESSIEstruct w;
  u8 digest[DIGESTBYTES];

  int i;
  for (i = 0; valor[i] != '\0'; i++);
  int sizeo = i;

  NESSIEinit(&w);
  NESSIEadd((u8*)valor, 8*sizeo, &w);
  NESSIEfinalize(&w, digest);

  return rb_str_new(displayHash(digest, DIGESTBYTES), 128);
}

到此為止,細分錯誤消失了。 但是返回的字符串帶有一個奇怪的字符,例如:

“ ruby​​ \\ x00 \\ x00 \\ x00 \\ x00 \\ x00未檢測到錯誤。\\ x00 \\ n \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ x00 \\ xD80x \\ xC0 \\ x18` \\ X18 \\ X18&F \\ XAF \\ X05#\\ x8C ## \\ XB8 \\ X91 \\ xF9〜\\ XC6?\\ XC6 \\ XC6 \\ XFB \\ xCDo \\ X13 \\ xE8 \\的x87 \\ xE8 \\ xE8 \\ XCB \\ X13 \\ xA1L \\的x87&\\的x87 \\的x87 \\ x11mb版權所有\\ xA9 \\ XB8 \\ XDA \\ XB8 \\ XB8 \\ t \\ X02 \\ X05 \\ b \\ X01 \\ X04 \\ X01 \\ X01 \\ r \\ x9EnBO!OO \\ x9Bl \\ XEE \\ xAD6 \\ xD866 \\ xFFQ \\ x04Y \\ xA6 \\ XA2 \\ xA6 \\ xA6 \\˚F\\ xB9 \\ XBD \\ XDE \\ xD2o \\ XD2"

僅當正確時才:

“紅寶石”

編輯3:

進行更改:

VALUE
print_string(VALUE class, VALUE *valor) {
  struct NESSIEstruct w;
  u8 digest[DIGESTBYTES];
 /*
  int i;
  for (i = 0; valor[i] != '\0'; i++);
  int sizeo = i;
 */
  NESSIEinit(&w);
  NESSIEadd((u8*)"ruby", 8*4, &w);
  NESSIEfinalize(&w, digest);

  return rb_str_new(displayHash(digest, DIGESTBYTES), 128);
}

返回正確的值。

然后我嘗試做到這一點:

VALUE
print_string(VALUE class, VALUE *valor) {
  struct NESSIEstruct w;
  u8 digest[DIGESTBYTES];
 /*
  int i;
  for (i = 0; valor[i] != '\0'; i++);
  int sizeo = i;
 */
  NESSIEinit(&w);
  NESSIEadd((u8*)"ruby", 8*4, &w);
  NESSIEfinalize(&w, digest);

  return rb_str_new2(valor);
}

期望返回“紅寶石”字符串。 但不是。 它返回:“ \\ x05”

那是什么意思?

for (i = 0; i < length; i++)

在此循環中,對於每一個通過條件,如果您將k遞增,那么這樣做將使數組超出范圍,從而導致崩潰。

確保

char *str = malloc( 3 * length + 1);

不是

char *str = malloc( 3 * (length + 1));

例如:

length = 2;

char *str = malloc(7);

現在,在for循環中,您將k增加4次。

k = 4;

現在,在第二次迭代之后,如果退出循環,則

k=8;

因此str[8]不是有效的訪問權限,可能會導致崩潰

首先,讓我感謝@FrederickCheung給我正確的方向。

解決方案代碼為:

VALUE
print_string(VALUE class, VALUE valor) {
  struct NESSIEstruct w;
  u8 digest[DIGESTBYTES];
  VALUE info;

  // Note here I must convert the Ruby VALUE type to C type. Thats is the trick. 
  char* valor2 = RSTRING_PTR(valor);

  int i;
  for (i = 0; valor2[i] != '\0'; i++);
  int sizeo = i;

  NESSIEinit(&w);
  NESSIEadd((u8*)valor2, 8*sizeo, &w);
  NESSIEfinalize(&w, digest);

  info = rb_str_new_cstr(displayHash(digest, DIGESTBYTES));

  return info;
}

對於想查看該代碼在哪里使用的人,可以訪問: https : //github.com/AngoDev/kryptonita

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM