# C 编译器警告信息问题说明
# 概要简述
Sysblock 支持用户通过 CCaller,CFunction 等模块使用外部 C 函数。由于外部 C 函数属于用户自定义的内容,可能存在各种各样的问题,导致编译模型失败。当问题发生时,根据 C 编译器的警告信息,我们能够较为便捷地定位问题产生的原因。因此本文档会对如何根据 C 编译器的警告信息,调试以及解决问题进行说明。
# C 编译器警告信息详细说明
在仿真设置的编译界面中存在是否“开启警告信息”的选项,如下图所示:
根据是否开启警告信息,存在不同的表现。
# 不开启警告信息
当没有开启警告信息时,比如我们通过 CCaller 模块使用一个外部 C 函数,在该函数中,我们使用到了一个未初始化的局部变量,函数内容如下图所示:
在该函数中,局部变量 b 没有初始化,就进行了使用。虽然编译器可能会赋予这个局部变量默认值,但这样的行为是不安全的。此时 Sysblock 的输出窗口是没有任何警告信息生成的。如果发生了问题,那么用户不能够便捷地定位问题的原因。
# 开启警告信息
当我们启用“开启警告信息”的选项时,此时如果在 Sysblock 中使用外部 C 函数,它的警告和错误信息会单独罗列出来,便于用户定位问题。
# CCaller 模块的问题定位流程
比如我们通过 CCaller 创建一个外部 C 函数,在 Sysblock 模型中使用。该函数的内容如下所示:
可以看出,该函数在使用 for 循环时,没有对循环变量 i 进行声明,并且它使用了 int 类型的变量去接收 double 类型的数组的值,模型会编译失败。由于我们启用了“开启警告信息”的选项,此时外部 C 函数的警告和错误信息会单独在 Sysblock 的输出窗口罗列出来,如下图所示:
此时我们可以通过输出窗口的警告和错误信息定位模型编译失败的原因。在上图中,红框标识出来的文件目录即为 CCaller 模块导入的外部 C 文件的所在位置。该信息表示在 Sort.c 的第 9 行出现了 double 类型的数据隐式转换为 int 类型的数据的行为。在 C 编译器看来,该操作是不安全的。至于“编译源文件”的内容则是外部 C 函数所生成的仿真文件的所在目录。我们可以根据此目录找到生成的仿真文件。
当然,我们也可以在仿真文件的输出目录中寻找 buildWarning.log 文件,如下图所示(文件目录仅供参考,以实际的输出目录为准):
buildWarning.log 文件的内容如下所示:
该 log 文件里的内容和 Sysblock 的输出窗口的警告信息的内容是一致的,我们同样可以在文件中找到外部 C 文件以及仿真文件的所在位置。buildWarning.log 文件只有在“开启警告信息”的选项启用,并且外部 C 函数确实存在编译上的问题时,才会生成。因此有时候,我们开启了警告信息的选项,但是没有对应的文件生成,可能是由于模型使用的 C 函数不存在编译上的问题。
根据上述的操作,我们已经定位了问题产生的原因,接下来就需要对问题进行修复。根据警告信息的提示,我们在对应的文件目录找到 CCaller 模块使用的 Sort.c 文件,如下所示:
对 Sort.c 文件中错误的地方进行修正,修正后的函数如下所示:
修正后的 CCaller 模块是可以正常仿真的,并且 Sysblock 的输出窗口是没有警告信息生成的,仿真文件的输出目录也没有 buildWarning.log 文件生成。此时可认为,我们已经解决了该外部 C 函数的问题。
# CFunction 模块的问题定位流程
当我们使用 CFunction 模块时,如果开启警告信息,它定义的 C 函数的信息也会单独罗列出来。比如我们使用了内容如下的 CFunction 模块:
arr 和 n 是 CFuntion 模块的输入变量,y 是输出变量,tmp 是未定义的局部变量。该模型实际上会编译失败。它的警告和错误信息同样会在 Sysblock 的输出窗口打印出来(此处同样可以在 buildWarning.log 中查看对应的日志信息),如下所示:
该信息主要包含 CFunction 函数的仿真文件的目录以及 C 编译器的警告和错误信息。一般来说,CFunction 函数的文件是在仿真文件目录的 extern_inc 子目录中生成的。我们也可以直接根据输出窗口中的文件目录,也就是上图中红框标识出来的内容,找到生成的仿真的 C 文件:
文件内容如下所示:
注释“Current Block Name”表示该函数属于哪一个 CFunction 模块。注释“Cfunction Code Divsion”里的代码,即为用户在 CFunction 模块里中编写的内容。一般来说,CFunction 模块生成的外部 C 函数的命名风格由“模型名” + “模块名” + “CFunction”构成。
根据 C 编译器信息的提示,我们需要对 tmp 变量进行声明,此时有两种修改方法。一种方式是在 CFunction 模块里对 tmp 变量进行手动声明,如下所示:
另一种方式是在 CFunction 模块里定义一个参数 tmp ,这样 Sysblock 在仿真时会自动生成该变量,不需要用户手动声明:
经过上述的修改,该 CFunction 模块可以正常仿真,输出窗口不会有警告信息生成,buildWarning.log 文件也不会在仿真文件的输出目录中生成。