Types 常见的Lisp类型注释会导致不健康的行为吗?

Types 常见的Lisp类型注释会导致不健康的行为吗?,types,common-lisp,declare,Types,Common Lisp,Declare,我知道,如果安全设置较低,Common Lisp可以使用类型注释作为优化辅助工具,并且不会进行检查。例如,此程序运行并打印数字和字符串,没有任何类型错误。(当安全>=1时,我仅在SBCL中获得类型错误) 我现在想知道,如果安全设置为零并且不尊重类型注释,是否有可能创建一个做坏事的程序。比如从一种类型转换到另一种类型(比如C类型转换)以及其他类型的未定义行为 (declaim (optimize (speed 3) (safety 0)

我知道,如果安全设置较低,Common Lisp可以使用类型注释作为优化辅助工具,并且不会进行检查。例如,此程序运行并打印数字和字符串,没有任何类型错误。(当安全>=1时,我仅在SBCL中获得类型错误)

我现在想知道,如果安全设置为零并且不尊重类型注释,是否有可能创建一个做坏事的程序。比如从一种类型转换到另一种类型(比如C类型转换)以及其他类型的未定义行为

(declaim (optimize
           (speed 3)
           (safety 0)
           ))

(defun f ()
    (let ((arr (make-array '(5)
      :element-type 'fixnum
      :initial-contents (list 1 2 3 4 5))))
      (declare (type (vector fixnum 5) arr))
      (setf (aref arr 0) "hello")
      (aref arr 0)))

(format t "a1 ~A~%" (f))
到目前为止,我还没有找到一个这样的例子。我尝试了这个示例中使用类型化数组的变体,但都没有导致类型转换行为

(declaim (optimize
           (speed 3)
           (safety 0)
           ))

(defun f ()
    (let ((arr (make-array '(5)
      :element-type 'fixnum
      :initial-contents (list 1 2 3 4 5))))
      (declare (type (vector fixnum 5) arr))
      (setf (aref arr 0) "hello")
      (aref arr 0)))

(format t "a1 ~A~%" (f))
在CLISP中,此程序打印“hello”,而不执行int类型转换,在SBCL中,程序会因简单类型错误而中止


如果我不尊重我的类型声明,有没有一种方法可以创建一个通用的Lisp程序,导致恶魔从我鼻子里冒出来?

不确定恶魔是什么,但是你可以得到一个segfault,就像我15年多前使用CMUCL时做的那样,类似于下面的代码:

(declaim (optimize (speed 3) (safety 0)))
(defun f (v)
  (declare (type (vector double-float) v))
  (loop for x in v sum x))
(f #(1 2 3))

请注意,我承诺我只会将
(向量双浮点)
传递给
f
,然后我用
fixnum
s给它一个
简单向量。

不确定恶魔,但你可以得到一个segfault,就像我15年多前用CMUCL做的那样,还有类似于此代码的东西:

(declaim (optimize (speed 3) (safety 0)))
(defun f (v)
  (declare (type (vector double-float) v))
  (loop for x in v sum x))
(f #(1 2 3))

请注意,我承诺只将
(向量双浮点)
传递给
f
,然后我用
fixnum
s给它一个
简单向量。它并没有真正说明它们做了什么,或者实现会对它们做什么

目的:

  • 生成特定于类型的代码
  • 运行时和/或编译时类型检查。这主要是由CMUCL、SBCL和SCL完成的
假设我们有了手术:

(+ i 100)
默认情况下,它将是一个通用的
+
,可以处理所有数字类型

如果我们告诉
i
fixnum
,那么

  • +
    操作可以是特定于fixnum的
如果另外将返回类型声明为
fixnum

  • 它可能不会溢出到bignum中
如果我们告诉编译器我们需要低
安全性
,那么编译器将不会生成运行时类型检查

编译器提供的功能没有标准化。它甚至可以完全忽略类型声明

如果您有一个支持特定类型代码的编译器(并且有许多这样的编译器),那么安全性很低,并且一个编译器在运行时提供了错误类型的对象,那么它可能会产生不必要的后果。包括由于堆内存损坏而导致Lisp崩溃

因此,最好仅在非常小的代码区域上使用低安全性,而不是在整个文件或系统上使用低安全性。将声明与
本地一起使用
会有所帮助


SBCL(也称为SCL和CMUCL)是特殊的,因为它还将类型声明视为用于类型检查的断言。

公共Lisp标准说存在类型声明。它并没有真正说明它们做了什么,或者实现会对它们做什么

目的:

  • 生成特定于类型的代码
  • 运行时和/或编译时类型检查。这主要是由CMUCL、SBCL和SCL完成的
假设我们有了手术:

(+ i 100)
默认情况下,它将是一个通用的
+
,可以处理所有数字类型

如果我们告诉
i
fixnum
,那么

  • +
    操作可以是特定于fixnum的
如果另外将返回类型声明为
fixnum

  • 它可能不会溢出到bignum中
如果我们告诉编译器我们需要低
安全性
,那么编译器将不会生成运行时类型检查

编译器提供的功能没有标准化。它甚至可以完全忽略类型声明

如果您有一个支持特定类型代码的编译器(并且有许多这样的编译器),那么安全性很低,并且一个编译器在运行时提供了错误类型的对象,那么它可能会产生不必要的后果。包括由于堆内存损坏而导致Lisp崩溃

因此,最好仅在非常小的代码区域上使用低安全性,而不是在整个文件或系统上使用低安全性。将声明与
本地一起使用
会有所帮助


SBCL(也称为SCL和CMUCL)是特殊的,因为它还将类型声明视为类型检查的断言。

这里有几个SBCL中的
安全0
示例:

CL-USER> (proclaim '(optimize (safety 0)))
; No value
越界阅读
在SBCL中,如果你闻到鼻魔的气味,你可以在加载有问题的代码之前重新启动图像并输入
(sb ext:restrict compiler policy'safety 3)
(也可以使用
'debug
)。幸运的是,这将为您带来一个良好的条件,而不是未定义的行为。

这里有几个sbcl中的
safety 0
示例:

(declaim (optimize
           (speed 3)
           (safety 0)
           ))

(defun f ()
    (let ((arr (make-array '(5)
      :element-type 'fixnum
      :initial-contents (list 1 2 3 4 5))))
      (declare (type (vector fixnum 5) arr))
      (setf (aref arr 0) "hello")
      (aref arr 0)))

(format t "a1 ~A~%" (f))
CL-USER> (proclaim '(optimize (safety 0)))
; No value
越界阅读
在SBCL中,如果你闻到鼻魔的气味,你可以在加载有问题的代码之前重新启动图像并输入
(sb ext:restrict compiler policy'safety 3)
(也可以使用
'debug
)。如果运气好的话,这将为您提供一个良好的条件,而不是未定义的行为。

我不知道这是否是恶魔,但在CCL中,您的程序会打印:
a1 6614253635515
。对于SBCL,类型推断知道本地创建值的类型。sds的答案显示了解决这个问题的好方法。@Xach:你能举个例子吗?在SBCL上运行sds的示例会给我一个
#(1 2 3)不是列表错误,而是我想要的无意义值。如果这是一个恶魔,我不知道。但是在CCL中,您的程序会打印:
a1 6614253635515
。对于SBCL,键入
(declaim (optimize
           (speed 3)
           (safety 0)
           ))

(defun f ()
    (let ((arr (make-array '(5)
      :element-type 'fixnum
      :initial-contents (list 1 2 3 4 5))))
      (declare (type (vector fixnum 5) arr))
      (setf (aref arr 0) "hello")
      (aref arr 0)))

(format t "a1 ~A~%" (f))