当没有提供参数时,Ruby 的 *args 会导致段错误
我正在尝试使用 Ruby 在 Windows 中进行一些脚本化 GUI 测试。我正在利用 pragprog 书籍的指导我遇到了一些障碍。我提取了一些代码来帮助重复映射 win32api 函数。代码如下:
module WindowsGui
def self.def_api(function, parameters, return_value)
api = Win32API.new 'user32', function, parameters, return_value
define_method(function.snake_case) do |*args|
api.call *args
end
end
end
...所以我可以使用该块以以下方式在模块中定义多个 win32API:
def_api 'FindWindow', ['P', 'P'], 'L'
我进行了一些 RSpec 测试以确保其行为符合预期。
it 'wraps a Windows call with a method' do
find_window(nil, nil).should_not == 0
end
it 'enforces the argument count' do
lambda {find_window}.should raise_error
end
第一次测试一切正常,第二次测试则导致段错误。似乎如果我在没有参数的情况下调用它,我就无法触摸 *args - 但我可以执行 args.length 来查看它是空的。
为什么这会导致段错误而不是异常?通过类似的方式解决这个问题是否可以接受。
raise BadArgs if args.length == 0
另一个太长的问题 - 对此感到抱歉。
蒂亚! 鲍勃
I'm trying to do some scripted GUI testing in Windows using Ruby. I'm leveraging the guidance of a pragprog book and I'm hitting a bit of a snag. I've factored out some code to help with the repeatitive mapping of win32api functions. The code is as follows:
module WindowsGui
def self.def_api(function, parameters, return_value)
api = Win32API.new 'user32', function, parameters, return_value
define_method(function.snake_case) do |*args|
api.call *args
end
end
end
...So I can use that block to define several win32APIs in the module in the following fashion:
def_api 'FindWindow', ['P', 'P'], 'L'
I've got some RSpec tests to ensure this behaves as it should.
it 'wraps a Windows call with a method' do
find_window(nil, nil).should_not == 0
end
it 'enforces the argument count' do
lambda {find_window}.should raise_error
end
Everything works fine as for the first test, the second results in a seg fault. Seems that if I call this with no args, I can't touch *args - but I can do a args.length to see that it's empty.
Why would this result in a seg fault and not an exception? Would it be acceptable to resolve this through something like..
raise BadArgs if args.length == 0
Yet another question that is way too long - sorry for that.
TIA!
Bob
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
出现段错误的可能原因是在
Win32API
下的某处,缺少参数会转化为一个或多个 NULL 指针取消引用。如果您要创建这样的函数,那么您应该考虑添加一个每次 api 调用、返回布尔值的参数验证块(或 lambda)作为
def_api
的参数,然后将其作为派生函数的第一部分。像这样的事情:然后
更新:根据提问者的要求添加更多颜色
&valid_args?
是块参数的名称。和符号前缀 (&) 是告诉 ruby 您传递了一个块的方式。您只能将一个块传递给方法,并且它必须是参数列表中的最后一个参数。问号后缀 (?) 只是 Ruby 编程中用于命名返回布尔值的函数的约定。如果传递了一个块,则可以使用
&block.call(args)
调用它 要使用块参数调用方法,您可以执行如下操作:
或者
传递
args
通过调用方法
到块。希望这有帮助。The likely reason it's seg faulting is because somewhere underneath
Win32API
the lack of arguments is translating into one or more NULL pointer dereferences.If you are going to create functions like this then you should consider adding a per-api-call, boolean-returning argument validation block (or lambda) as an argument to
def_api
which you would then invoke as the first part of your derived function. Something like this:Then
UPDATE: Adding more color at questioner's request
The
&valid_args?
is the name of a block parameter. The ampersand prefix (&) is how you tell ruby that you passing a block. You can only pass one block to a methodand it must be the last parameter in the argument list. The question mark suffix (?) is just a convention in Ruby programming for naming functions which return boolean values.If a block is passed you invoke it with
&block.call(args)
To call a method with a block argument you do something like this:
or
The
args
are passed to the block through thecall method
. Hope this helps.