Qizhen's profileLabVIEWPhotosBlogListsMore ![]() | Help |
LabVIEW 代码中常见的错误 发现了程序的问题再回头去调试,在查找程序错误时就不可避免地要花大量时间。要调高开发效率,最好是在编写代码时就避免一些常见的低级错误,这样可以节约大量的调试时间。 1. 数值溢出 图1 中的 VI 只做了一个简单乘法 300*300 ,不加思索就应该知道答案是 90000,但程序中乘法节点给出的结果却是 24464。乘法节点是不会错的,错误是由于程序中使用的数据类型是 I16。I16 能表示的最大数目只有32767,所以在乘法计算中出现了溢出。 2. For 循环的隧道循环相关的介绍可以参考《循环结构》。 数据传入传出循环结构可以通过移位寄存器(Shift Register)和隧道(Tunnel)两种方式。隧道又有两种类型:带索引的和不带索引的。 图2中的程序, vi reference 传入,再传出循环均使用了隧道。如果循环次数为0(Controls数组为空),vi reference 再传出循环时,信息就丢失了。这不但有可能造成后续程序的错误,而且由于 vi reference 的信息丢失,再无法关闭打开的 vi,造成了程序泄漏。 3. 循环次数 与其它语言相比,LabVIEW 的 For 循环有一大特点,在某些情况下它并不要求一定要输入循环次数,而可以根据输入数组的大小自动决定循环次数。通过带索引的隧道,可以把数组分解成元素传递到循环体内,此时不需另行设置循环次数N,循环的次数就是数组的长度。每次循环,带索引的隧道便给出一个元素。 While 循环同样也可以使用带索引的隧道,但是我不建议大家这么用——如果需要用到带索引的隧道,还是使用 For 循环更为适宜。因为 while 循环的循环次数不由数组个数决定,而是由停止条件决定的。如使用了带索引的隧道,你还需要考虑当数组大于、小于循环次数时,程序应该如何处理,所以还是在循环体内作索引比较方便。如果希望循环次数与数组大小保持一致,那自然是用 For 循环的程序更加清晰易懂了。 4. 移位寄存器的初始化看图3中这个程序,因为它在 while 循环上使用了带索引的隧道,所以可读性不那么好。array out 的运行结果是什么,还要考虑一阵子才能给出答案。实际上这个程序,即使输入不变,每运行一次,array out 的结果都是不一样的,它的长度一直在增加。这个问题就出在没有给程序中的移位寄存器一个初始值。 没有初始化的移位寄存器,总是保存上次运行结束时的数据。这个特点在某些情况下可以被程序员利用,比如用它当作全局变量,随时把数据存入或取出(一个例子是《如何使用 VI 的重入属性》中的图4)。但多数情况下移位寄存器还是被用作为循环内部的局部变量的,这时就一定要对它初始化,以防止潜在的错误。 5. Cluster图4的程序中有个奇怪的错误,明明应该是 weight 加 1 怎么运行完后的结果变成了high 加 1 了呢?直接揭开谜底吧,原因是 Cluster 中的元素有个顺序,这个顺序可以和界面上看到的顺序不一致。分别鼠标右击程序中的两个 Cluster,选择“Reorder Controls in Cluster”,就可以看到每个元素在 cluster 中的编号。info out 中的 high 实际上编号是 2,第三个元素。 为了避免 cluster 中用可能出现的错误,以及让 cluster 应用起来更方便,使用 cluster 最好遵循以下原则: 6. 并行运行LabVIEW 是自动多线程的编程语言,这一点在方便用户的同时,也会带来一些麻烦。比如最常见的情况,多线程会引起数据或资源的竞争错误(race condition)。 图5是一个简单的两个子 VI 并行运行的例子,在这个例子中就隐藏着一个潜在的问题。并行执行的两部分程序,先后次序是不定的。有可能关闭程序中的引用数据(绿色的线上的数据)的节点在子 VI B 结束前运行。而子 VI B 是要用到这个参考数据的,这是子 VI B 就会因为它所需要的数据失效而产生错误。 下载示例: TrackbacksThe trackback URL for this entry is: http://ruanqizhen.spaces.live.com/blog/cns!5852D4F797C53FB6!1857.trak Weblogs that reference this entry
|
|
|