如何debug ruby

how to debug ruby:

1. 第一种方法,直接使用ruby内建的debug在命令行调试,这个个gdb或者pdb的命令差不多。

ruby -r debug yourubyfile.rb

2. 在eclipse中debug ruby

2.1 使用内建的ruby debugger,在上图中选择”Ruby Build-In Debugger”

2.2 使用Fast Ruby Debugger(ruby-debug),但是一般的ruby都没有ruby-debug包,所有需要自己安装。

但是1.8,1.9和2.0的安装都不一样。

如果你使用的是1.8
gem install ruby-debug-base
gem install ruby-debug
gem install ruby-debug-ide

如果你使用的是1.9
gem install ruby-debug-base19
gem install ruby-debug19

gem install ruby-debug-ide19

2.3 使用ActiveState,我没有使用过。

NOTE:

1. 现在ruby-debug还不支持 ruby 2.0
2. 有时,远程安装不上或者很长时间没有反映,你可以自己将它们下载到本地,使用–local安装
例如: ruby 1.8
ruby-debug-base-0.10.4.gem
linecache-0.46.gem #这里是依赖关系
bx-require-relative-0.0.9.gem

ruby-debug-0.10.4.gem
columnize-0.3.6.gem

ruby-debug-ide-0.4.18.gem
rake-10.1.0.gem
minitest-5.0.7.gem

从rubygems.org将上面的八个gem包下载下来,放到同一个目录,然后使用下面的命令安装
gem install –local ruby-debug-base-0.10.4.gem
gem install –local ruby-debug-0.10.4.gem
gem install –local ruby-debug-ide-0.4.18.gem

3. ruby 1.8里面没有保护gem,所有需要我们自己安装
download it from rubygems.org, extract it,

ruby setup.rb

4. 如果使用gem时,提示说找不到ruby.h文件,说明你安装的ruby没有安装对于的头文件,

你可以自己从 https://ftp.ruby-lang.org/pub/rub 下载source包,自己编译和安装。

安装步骤为:

./configure
make
make check
make install

如果你想删除安装的文件,可以在ruby的source目录下:

cat .installed.list | xargs rm -rf

C++中内存访问越界出现的奇怪问题

程序的主要逻辑如下:

int fd;
int size = 0;
int bytes = 0;

if (openFile(filename, fd, size)) {
    char* buffer = new char[size];
    if ((bytes = ::read(fd, buffer, size))) { ...}

    for (int i=0; i<bytes; i++) {
        if (i==(bytes-1))  {
1)           buffer[i+1] = '\0'; //这里数组越界
        }
        ...
2)        string fileStr(linePointer);
    }
    ...
3)    delete[] buffer;

}

因为是公司内部的代码,所以不能贴出详细的代码。

上面的代码运行时,会在1)处访问超出数组buffer的边界,因为在C++中数组下标时从0开始的,所有array[array.length]会越界。

但是在具体的运行时,会出现奇怪的问题。

有时会在2)处抛出:
glibc detected program: malloc(): memory corruption (fast):
0x00002aaabd0c3650 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3e99a73b1c]
/lib64/libc.so.6(__libc_malloc+0x6e)[0x3e99a74e4e]
/usr/lib64/libstdc++.so.6(_Znwm+0x1d)[0x3e9eabd1dd]
/usr/lib64/libstdc++.so.6(_ZNSs4_Rep9_S_createEmmRKSaIcE+0x21)[0x3e9ea9b861]
/usr/lib64/libstdc++.so.6[0x3e9ea9c365]
/usr/lib64/libstdc++.so.6(_ZNSsC1EPKcRKSaIcE+0x42)[0x3e9ea9c512]

有时会在3)处抛出:
glibc detected program: double free or corruption (!prev):
0x0000000018553af0 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3e99a7247f]
/lib64/libc.so.6(cfree+0x4b)[0x3e99a728db]

刚开始的时候,像这种同一个代码段,在运行多次时,会在不同的地方出错,我以为时多线程问题,

后来一看代码,根本就没有多线程,所有否定。

再仔细看代码下,发现错误,内存访问越界。

所有我猜测,当C++中出现内存访问越界时,有可能会立即报错,也有可能在下一次/下下一次(在它的附近)
的内存访问(new or delete)时会报错,但是这时报出来的错误已经面目全非了。
所有像这种问题,还是需要仔细看代码的。

使用vi编辑binary文件

原理:使用xxd将当前文件转成hex格式,编辑,然后再转回去

/usr/bin/xxd

xxd - make a hexdump or do the reverse

例子:

用binary模式启动vi

vi -b test.txt

将所有内容转成hex

:%!xxd

修改你想改的地方;

然后将所有内容转成binary

:%!xxd -r

那么:%!xxd是什么意思呢?

:表示进入vi的命令mode;

%表示当前文件的所有内容,和1,$一样

!表示要执行Linux命令,它后面跟的是需要执行的Linux命令

所以::%!xxd 和:1,$ !xxd的效果一样;

如果想改变xxd的输出groupsize,可以使用-g。

例如::%!xxd -g 1的输出效果如下。

Note:其实%,$等符合是从ex editor来的。具体可参见 Learning the vi and Vim Editors.pdf 一书。

http://vim.wikia.com/wiki/Hex_dump

javascript中的继承方法

Javascript面向对象编程(二):构造函数的继承 这里,可以看到详细的说明。

我只是将其中的例子做成html文件,便于调试罢了。

1. 构造函数绑定

<html>
<head>
<script type="text/javascript">
function Animal(){
    this.species = "动物";
}

Animal.prototype.species2 = "动物2"

function Cat(name,color){
    Animal.apply(this, arguments);
    this.name=name;
    this.color=color;
}
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){alert("吃老鼠")}; 

var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");
alert(cat1.species); // 大毛
alert(cat1.species2); // 黄色
</script>
</head>
<body>
    Test
</body>
</html>

但是这种方法只适合本地变量的继承,并且Animal和Cat之间也没有关系。

看截图,可以看到从cat1并不能访问Animal.prototype.species2。

2。 prototype模式

<html>
<head>
<script type="text/javascript">
function Animal(){
    this.species = "动物";
}

function Cat(name,color){
    this.name=name;
    this.color=color;
}

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){alert("吃老鼠")}; 

var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");
alert(cat1.name); // 大毛
alert(cat1.color); // 黄色
</script>
</head>
<body>
    Test
</body>
</html>

从截图可以看出,prototype还是没有改变javascript内部的继承关系,见直角方框;

圆角方框中的内容就是通过改变prototype,来实现继承。

3. 直接继承prototype

<html>
<head>
<script type="text/javascript">
function Animal(){ }
Animal.prototype.species = "动物";

function Cat(name,color){
    this.name=name;
    this.color=color;
}

Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;

Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){alert("吃老鼠")}; 

var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");
alert(cat1.name); // 大毛
alert(cat1.color); // 黄色
</script>
</head>
<body>
    Test
</body>
</html>

从下面的截图上可以看出,修改Cat.prototype会同时修改Animal.prototype。

4. 利用空对象作为中介

<html>
<head>
<script type="text/javascript">
function extend(Child, Parent) {
  var F = function(){};
  F.prototype = Parent.prototype;
  Child.prototype = new F();
  Child.prototype.constructor = Child;
  Child.uber = Parent.prototype;
}

function Animal(){ }
Animal.prototype.species = "动物";
Animal.prototype.birthPlaces = ['北京','上海','香港'];

function Cat(name,color){
    this.name=name;
    this.color=color;
}

extend(Cat,Animal);

Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){alert("吃老鼠")}; 


var cat1 = new Cat("大毛","黄色");
cat1.birthPlaces.push('厦门');
var cat2 = new Cat("二毛","黑色");
alert(cat1.name); // 大毛
alert(cat1.color); // 黄色
</script>
</head>
<body>
    Test
</body>
</html>

但是这种方法,还是存在子类修改父类的方法。

cat1.birthPlaces.push('厦门');

会直接导致Animal中的birthPlaces变量变化,这时就会牵扯到浅拷贝和深拷贝了。

一句话,上面的方法,都是在模拟继承,但是都不是正的继承。

javascript中现在还不支持继承,只能能下一个版本。

非构造函数的继承的详细解释

Javascript面向对象编程(三):非构造函数的继承 这里,可以看到详细的说明。

我只是将其中的例子做成html文件,便于调试罢了。

<html>
<head>
<script type="text/javascript">
function extendCopy(p) {
    var c = {};

    for (var i in p) {
        c[i] = p[i];
    }
    c.uber = p;

    return c;
}

function deepCopy(p, c) {
    var c = c || {};

    for (var i in p) {
        if (typeof p[i] === 'object') {
            c[i] = (p[i].constructor === Array) ? [] : {};
            deepCopy(p[i], c[i]);
        } else {
            c[i] = p[i];
        }
    }

    return c;
}

function object(o) {
    function F() {}
    F.prototype = o;

    return new F();
}

var Chinese = {
    nation:'中国'
};
var Doctor = object(Chinese);
Doctor.career = '医生';
alert(Doctor.nation);

Chinese.birthPlaces = ['北京','上海','香港'];
var Doctor2 = extendCopy(Chinese);
//change child
Doctor2.birthPlaces.push('厦门');
alert(Doctor2.birthPlaces);
alert(Chinese.birthPlaces);

var Doctor3 = deepCopy(Chinese);
//change child
Doctor3.birthPlaces.push('厦门2');
alert(Doctor3.birthPlaces);
alert(Chinese.birthPlaces);
</script>
</head>
<body>
    Test
</body>
</html>

下面时从web developer debugger上的截图。

1.通过继承来获得Chinese的nation和birthPlaces属性。

2. 这里时浅copy,所有更改Doctor会同时更改Chinese

3. 这里时深copy,所有Doctor和Chinese互不影响。

javascrip中的继承

“实例对象一旦创建,将自动引用prototype对象的属性和方法。也就是说,实例对象的属性和方法,分成两种,一种是本地的,另一种是引用的。”

从java的角度来说,

实例对象的本地属性和方法就是private方法或者变量,只对当前的实例对象可见;

实例对象从prototype对象继承的属性和方法就是public方法或者变量,不仅对当前的实例对象可见,而且对它的子类可见;

这被称为 Prototype继承模型

可以通过 isPrototypeOf() 方法来检查某个对象是否在实例的prototype chain中;

可以通过 hasOwnProperty() 方法来区分本地属性和从prototype继承来的属性;

但是我在实验 isPrototypeOf() 方法时,发现一个问题:

例如下面的例子:

function Person(name,color){
this.name=name;
this.color=color;
}

var p = new Person(“a”, “b”);
console.log(Person.prototype.isPrototypeOf(p))
// true
console.log(Function.prototype.isPrototypeOf(p))
// false
console.log(Object.prototype.isPrototypeOf(p))
// true

从web developr debugger上的截图上,可以看出,Function类时在p实例的prototype
chain上,但是为什么返回false呢。

http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-
works.html


http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html

https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Object/isPrototypeOf?redirectlocale=en-
US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2FisPrototypeOf

在javascript中获得一个对象的所有方法

Object.getOwnPropertyNames(Object.prototype)
Object.getOwnPropertyNames(Object)

以下是在firebug上运行的结果:

Object.getOwnPropertyNames(Object.prototype)

[“constructor”,
“toSource”,
“toString”,
“toLocaleString”,
“valueOf”,
“watch”,
“unwatch”,
“hasOwnProperty”,
“isPrototypeOf”,
“propertyIsEnumerable”,
defineGetter“,
defineSetter“,
lookupGetter“,
lookupSetter“]

Object.getOwnPropertyNames(Object)
[“prototype”,
“getPrototypeOf”,
“getOwnPropertyDescriptor”,
“keys”,
“is”,
“defineProperty”,
“defineProperties”,
“create”,
“getOwnPropertyNames”,
“isExtensible”,
“preventExtensions”,
“freeze”,
“isFrozen”,
“seal”,
“isSealed”,
“length”,
“name”,
“arguments”,
“caller”]

how to write extension for firefox -- 如何给firefox编写插件

1. 准备环境

1.1 创建一个dev profile

firefox -P

1.2 安装一些开发插件

firebug & web developer

1.3 创建或者修改一些preference

javascript.options.showInConsole = true
nglayout.debug.disable_xul_cache = true
browser.dom.window.dump.enabled = true
javascript.options.strict = true
devtools.chrome.enabled = true
devtools.debugger.remote-enabled = true
extensions.logging.enabled = true
nglayout.debug.disable_xul_fastload = true
dom.report_all_js_exceptions = true
devtools.errorconsole.deprecation_warnings = true

1.4 启动firefox

firefox -no-remote -P dev

使用-no-remoet可以使你同时用自己平时使用的profile浏览网页,和你开发的profile互补干扰。


https://developer.mozilla.org/en/docs/Setting_up_extension_development_environment

2. 修改别人的extension

http://kb.mozillazine.org/Getting_started_with_extension_development

http://mozilla.doslash.org/stuff/helloworld.zip

Note 1:当你修改install.rdf中有关firefox的compatile
version时,有时会提示你版本不兼容当前的firefox,不要理会,

清空你的工作环境从新从头开始就好了。

Note 2: 不管你时修改了install.rdf还是别的文件,都需要重新启动firefox来重新加载你的extension

3. 打包

只要把chrome.manifest中注册的目录和install.rdf打包成zip文件,然后重命名成xpi文件,就可以在firefox上安装了。