简介:这份PDF文档对应GAMES101计算机图形学课程作业0,由闫令琪授课,面向刚接触图形学编程、需要搭建统一开发环境的学习者,重点解决虚拟机配置与作业框架运行的环境准备问题。全文围绕VirtualBox安装、虚拟硬盘挂载、Guest Additions增强功能配置、作业框架拖放传输与VSCode编辑等环节展开,并附有C++基础语法说明,以及编译错误、链接错误、段错误等常见问题的排查提示,可作为动手前的环境手册。压缩包共1个文件,为1份PDF文档,大小约874KB,篇幅精简,便于随时查阅对照。目前已有435人学习下载。读者可据此在Windows、Mac OS或Linux主机上完成Ubuntu虚拟机的搭建,减少环境差异带来的重复试错,把精力集中到后续图形学编程练习上。
1. 虚拟机一启动就报错:图形学作业0 的环境卡点比代码更折腾
图形学作业0 的虚拟机环境,最容易把人卡在第一步:虚拟硬盘明明下载完了,挂载时却提示打不开磁盘映像;好不容易进系统,增强功能装到一半报内核模块加载失败;把作业框架拖进去,编译又报头文件找不到。这个作业0 本身只要求把一个点绕原点旋转再平移,用齐次坐标算一遍,代码量并不大,真正耗时间的是虚拟机、挂载、拖放和构建这一串环境问题。下面按我踩过的顺序,从虚拟硬盘挂载、增强功能安装、框架传输,到编译运行报错,一条条拆开。适合刚拿到作业0 文档、虚拟机还没跑通,或者已经能启动但卡在拖放和编译的人。
2. 虚拟硬盘挂载失败:三种“打不开磁盘映像”的排查顺序
虚拟硬盘挂载失败是最先劝退的一类报错。表面上看是虚拟机软件不认文件,实际常见的根因只有三类:文件没解压完整、路径或扩展名被系统处理坏了、宿主机虚拟化能力没开或内存不够。排查顺序不要从重装虚拟机开始,先看文件本身,再看宿主机开关,最后看启动日志。这样能少走很多弯路,也不会把已经下载好的虚拟硬盘反复删掉重下。
2.1 报“打不开虚拟硬盘文件”:先确认解压完整、扩展名和路径
这个报错通常出现在新建虚拟机、选择已有虚拟硬盘文件的那一步。弹窗会说无法打开磁盘映像,或者格式不支持。很多人第一反应是文件损坏,其实更常见的是压缩包只解压了一半,或者解压工具把扩展名藏起来了,导致你选中的是一个临时文件。还有一种情况是虚拟硬盘放在中文路径、带空格的目录里,虚拟机软件读取时转义失败。先别急着换虚拟机软件,拿文件大小和真实类型做一次核对。
# 查看虚拟硬盘文件大小,确认不是几 KB 的残留文件 ls -lh ./图形学作业0虚拟硬盘.vdi # 查看文件真实类型,避免扩展名被隐藏后选错文件 file ./图形学作业0虚拟硬盘.vdi # 如果路径里有中文或空格,先挪到纯英文目录再挂载 mkdir -p ~/vm/disk mv ./图形学作业0虚拟硬盘.vdi ~/vm/disk/这段命令的逻辑是先确认文件完整性和真实格式,再处理路径问题。ls -lh看的是文件大小是否和下载页描述一致,如果只有几百 KB,基本就是解压中断。file不依赖扩展名,能看出它到底是不是虚拟硬盘格式。最后一步不是必须,但当路径里有中文、空格、括号时,先挪到~/vm/disk这种纯英文短路径,能排除一大批“文件明明在,软件就是不认”的玄学问题。
注意,解压时不要只解外层压缩包。有些资源是压缩包套压缩包,外层解完得到一个目录,里面才是虚拟硬盘文件。如果你选中目录而不是文件,也会报打不开。正确的做法是进到目录里,确认文件扩展名和大小,再在虚拟机软件里选择“使用已有的虚拟硬盘文件”。
2.2 启动报“虚拟化不可用”或直接黑屏:先开宿主机开关,再排冲突
文件能挂上,不代表能启动。常见现象是点击启动后立刻报虚拟化不可用,或者窗口黑屏几秒后退出。根因通常不在虚拟机内部,而在宿主机:固件里的虚拟化开关没开,或者宿主机上已经有其他虚拟化组件占用了能力。还有一种容易被忽略的情况是内存给得太小,系统启动到图形界面时直接卡死。先看宿主机还剩多少内存,再看虚拟化开关,顺序别反。
# 看宿主机当前内存和可用内存,确认分 2GB 给虚拟机后不会把宿主机压死 free -h # 看虚拟硬盘所在分区剩余空间,快照和日志也会占空间 df -h ~/vm/diskfree -h重点看 available 那一列,不是看 total。如果宿主机总共只有 4GB,可用不到 2GB,虚拟机给 2GB 就会频繁换页,表现为启动极慢或黑屏。df -h看的是虚拟硬盘所在分区,剩余空间不足时,虚拟机启动到一半写日志失败,也会退出。常见做法是给虚拟机留 2GB 内存,同时保证宿主机至少还有 2GB 可用;如果宿主机内存紧张,先把浏览器和大型应用关掉,再启动虚拟机。
虚拟化开关在固件设置里,不同机器名字不一样,常见的是虚拟化技术、硬件虚拟化、VT-x、AMD-V 这类选项。这个开关不开,虚拟机软件只能做软件模拟,启动会非常慢,甚至直接报错。另一个常见冲突是宿主机自带的虚拟化功能已经占用了能力,比如某些安全组件、容器桌面、旧版虚拟机残留。排查时先关掉不用的虚拟化组件,重启宿主机,再启动虚拟机。不要一上来就改虚拟机配置,先确认宿主机让不让它跑。
2.3 能启动但卡在登录界面:内存、磁盘满和异常关机快照
比“打不开”更折磨的是“能启动,但进不去”。现象是卡在登录界面,输入密码后黑屏,或者登录后又弹回登录界面。这类问题一般不是密码错,而是系统内部资源不够或者文件系统有问题。虚拟机内存太小、根分区满了、上次异常关机留下损坏的快照,都会导致登录循环。先看磁盘,再看内存,最后看快照。
# 在虚拟机内看根分区使用率,磁盘满会导致登录会话无法创建 df -h / # 在宿主机看虚拟硬盘目录占用,异常快照会迅速吃掉空间 du -sh ~/vm/diskdf -h /看的是虚拟机内部根分区,使用率到 95% 以上就要清理。常见占满空间的是下载目录、旧构建目录和日志文件。du -sh在宿主机执行,看虚拟硬盘目录整体占用,如果比虚拟硬盘文件本身大很多,说明有快照或日志残留。遇到登录循环,可以先在虚拟机设置里检查有没有不需要的快照,删掉旧快照再启动;如果磁盘满,进恢复模式或挂载虚拟硬盘清理空间。注意不要直接删虚拟硬盘文件,那是把系统盘整个删掉。
还有一个容易翻车的点:虚拟机没有正常关机,直接关窗口,下次启动可能提示磁盘需要检查。这个时候不要反复强制关机,让它把文件系统检查跑完。如果检查卡住,再考虑从快照回退。排查顺序固定为:文件完整性、宿主机虚拟化开关、内存和磁盘、快照状态。按这个顺序走,大部分“打不开”和“启动黑屏”都能定位到具体一层。
3. 增强功能装不上:分辨率、拖放、共享粘贴集体失效怎么办
增强功能装不上,表现很集中:分辨率只能停在很小的窗口,鼠标移进虚拟机要按特殊键才能出来,宿主机和虚拟机之间不能拖放文件,复制粘贴也失效。很多人以为这是虚拟机软件坏了,实际多半是增强功能安装脚本没跑完,或者内核头文件不匹配导致模块没加载。这个环节要分清“安装脚本执行失败”和“安装成功但模块没生效”,两者的处理方式不一样。
3.1 菜单安装没反应:先手动挂载虚拟光驱,再执行安装脚本
点击菜单里的安装增强功能后,常见现象是没有任何弹窗,或者虚拟机里多了一个光驱图标但点不开。根因通常是虚拟光驱没有自动挂载,或者当前用户没有权限读取挂载点。不要反复点菜单,直接开终端手动挂载,看到安装脚本再执行。这样能确认到底是光驱没挂上,还是脚本执行失败。
# 手动创建挂载点并挂载虚拟光驱 sudo mkdir -p /media/cdrom sudo mount -t auto /dev/cdrom /media/cdrom # 查看挂载目录里有没有安装脚本 ls -l /media/cdrom # 进入挂载目录执行安装脚本,脚本名以实际目录为准 cd /media/cdrom sudo sh ./<增强功能安装脚本>.runmkdir -p保证挂载点存在,mount -t auto让系统自动识别光驱文件系统。ls -l是为了确认脚本真的在,如果目录是空的,说明虚拟光驱没挂上,或者菜单操作没有把光盘放进虚拟光驱。执行脚本必须用sudo,因为安装过程要写系统目录和内核模块。脚本名不要照抄,进目录看一眼实际文件名,把<增强功能安装脚本>替换成真实名字。
如果挂载时报“设备不存在”,先在虚拟机设置里确认光驱设备存在,并且没有指向一个空文件。常见做法是先关掉虚拟机,在存储设置里检查光驱控制器,再启动。挂载成功后不要急着重启,先看脚本输出最后几行有没有报错,很多失败其实在终端里已经写清楚了。
3.2 安装报内核头文件缺失:版本要对,编译工具要全
命令行安装跑到一半,提示找不到内核头文件,或者模块编译失败。这个根因很直接:当前运行的内核版本和已安装的头文件版本不一致,安装脚本没法编译增强功能模块。另一个原因是缺少编译工具,脚本连编译环境都凑不齐。先确认内核版本,再装对应版本的头文件和基础编译工具,最后重跑脚本。
# 确认当前内核版本,后面装头文件要和它完全对应 uname -r # 更新包索引,安装当前内核对应的头文件和编译工具 sudo apt-get update sudo apt-get install -y linux-headers-$(uname -r) build-essential # 重新进入光驱目录执行增强功能安装脚本 cd /media/cdrom sudo sh ./<增强功能安装脚本>.rununame -r输出的是当前内核版本,linux-headers-$(uname -r)会把这个版本拼进包名,保证头文件和内核匹配。build-essential提供编译器和基础构建工具,缺它的时候脚本会报找不到编译器。apt-get update不能省,包索引太旧会装到不存在的版本。重跑脚本前不需要重启,但安装完成后必须重启虚拟机,模块才会加载。
如果安装完仍然报模块加载失败,先看是不是安全启动限制。某些宿主机开启了安全启动,第三方内核模块会被拒绝加载。这个时候要么在固件设置里调整安全启动,要么接受增强功能不可用,改用共享目录传文件。不要为了装增强功能反复重装系统,先确认根因在哪一层。
3.3 拖放设置成双向还是不能拖:模块、重启顺序和文件大小
设备菜单里已经把拖放设置成双向,但拖文件进去没有任何反应。这个现象最容易让人怀疑人生。常见原因有三个:增强功能模块根本没加载;设置改变后没有重启虚拟机;拖放本身对大文件或文件夹支持不好。先验证模块,再重启,最后用共享目录兜底。
# 查看增强功能相关模块是否加载,模块名按实际环境替换 lsmod | grep -i guest # 查看当前用户所属组,确认有权限访问共享目录 idlsmod列出已加载模块,如果搜不到增强功能相关模块,说明安装没生效,回到 3.1 和 3.2 重装。id看当前用户组,共享目录通常要求用户在特定组里,不在组里会表现为能看到目录但打不开。设置双向拖放后,正确顺序是先关机,再启动,而不是在运行中反复切换。如果还是不行,不要死磕拖放,直接在虚拟机设置里配共享目录,把作业框架放到共享目录里,再从虚拟机内拷贝到工作目录。共享目录比拖放稳定,尤其是文件夹和大量小文件。
4. 作业框架拖不进虚拟机:文件传输、权限和编辑器打开报错
作业框架传不进去,或者传进去打不开,是作业0 第二个高频卡点。拖放失败只是表面现象,背后可能是增强功能没生效、文件落在了错误目录、文件所有者变成 root、中文路径导致构建工具解析失败。这个环节的目标不是“把文件弄进去”就完事,而是让文件在虚拟机里可读、可写、可编译。传进去之后立刻做权限和路径检查,比编译报错后再回头找要省时间。
4.1 拖进去找不到文件:先按文件名找,再统一工作目录
拖放操作没有明显进度条,文件可能落在桌面、下载目录,或者当前文件管理器打开的目录。更隐蔽的情况是文件名里有中文,拖进去后显示成乱码,你按原名找不到。先别重复拖,直接在用户目录下按文件名和常见源码文件搜一遍。找到后统一挪到纯英文工作目录,避免后面构建工具因为路径里的空格或中文报错。
# 在用户目录下按作业框架关键词查找,深度限制为 3 层,避免全盘扫描太慢 find ~ -maxdepth 3 -iname '*作业*' -o -iname '*main.cpp*' # 建一个纯英文工作目录,后续所有编译都在这里做 mkdir -p ~/work/graphics_hw0 # 把找到的框架目录挪进去,路径按实际查找结果替换 mv ~/Desktop/作业框架 ~/work/graphics_hw0/find的-maxdepth 3是防止扫描整个磁盘,-iname忽略大小写,-o表示两个条件任一满足。找到后不要直接在桌面或下载目录里编译,先挪到~/work/graphics_hw0这种纯英文、无空格路径。很多构建报错不是代码问题,而是路径里有中文或空格导致配置文件解析失败。统一工作目录还有一个好处:后面清理构建缓存时不会误删别的文件。
如果find什么都找不到,说明拖放根本没成功。回到第 3 章确认增强功能模块是否加载,或者改用共享目录。不要在这个阶段反复重装虚拟机,先确认文件到底有没有进到虚拟机文件系统里。
4.2 能打开但不能保存:文件所有者不对,别直接给 777
从宿主机拖进来的文件,所有者可能变成 root,或者权限变成只读。表现是编辑器能打开,但一保存就提示权限不足;终端里编译也可能因为无法写构建目录失败。很多人图省事直接chmod 777,这是血泪经验里最不建议的做法:权限放开后,后续文件被改坏都找不到原因。正确做法是把所有者改回当前用户,再给当前用户读写权限。
# 把作业框架所有权改回当前用户,$USER 会自动展开为登录用户名 sudo chown -R "$USER":"$USER" ~/work/graphics_hw0 # 只给当前用户增加读写权限,不要动其他用户的权限 chmod -R u+rw ~/work/graphics_hw0 # 确认关键文件权限和所有者 ls -l ~/work/graphics_hw0chown -R递归修改目录和文件所有者,"$USER":"$USER"分别对应用户和用户组。chmod -R u+rw只给所有者加读写,不碰组和其他人。ls -l用来确认main.cpp和构建配置文件的所有者是不是当前用户。如果文件所有者已经是当前用户,但仍然不能保存,检查父目录有没有写权限,或者文件是不是在只读共享挂载里。共享目录挂载通常由宿主机控制权限,虚拟机内改不了,这种情况把文件拷到本地工作目录再编辑。
4.3 编辑器打开文件夹报“没有权限”或中文乱码
编辑器打开作业框架文件夹时提示没有权限,或者打开后中文注释全是乱码。权限问题不一定是文件本身,可能是父目录缺少执行权限,导致你进不去目录。乱码则通常是文件编码不是 UTF-8。先用namei看路径上每一级权限,再用file -i看文件编码。这两个命令能快速区分“权限问题”和“编码问题”。
# 查看从根目录到 main.cpp 每一级的权限,重点看目录有没有 x 权限 namei -l ~/work/graphics_hw0/main.cpp # 查看文件编码,确认是不是 GBK 导致中文注释乱码 file -i ~/work/graphics_hw0/main.cppnamei -l会逐级列出路径权限,目录没有x权限时,即使文件本身可读,也打不开。file -i输出里如果看到charset=gbk之类,说明文件不是 UTF-8,编辑器需要切换编码打开。常见做法是把编辑器默认编码设成 UTF-8,再重新保存。不要直接用转码命令批量处理整个框架,先备份,再只转需要编辑的文件,避免把二进制文件转坏。
5. 编译与运行避坑:头文件找不到、链接错误、段错误的五条踩坑记录
编译和运行阶段的报错看起来最像“代码问题”,但作业0 的环境问题会伪装成编译错误。比如头文件路径没配对、构建目录进错、链接时漏了源文件、数组越界导致段错误、角度没转弧度导致结果不对。下面五条是我在作业0 里反复见到的翻车记录,每条按现象、原因、解决写。先把这五类排掉,再去看图形学变换公式,效率会高很多。
5.1 现象:fatal error: 某头文件: No such file or directory
现象是编译刚开始就报找不到头文件,后面跟一个路径或库名。原因通常有三个:头文件搜索路径没配、依赖库没装、代码里大小写写错。Linux 文件系统区分大小写,Vector和vector是两个东西。解决时先确认头文件在不在,再补包含路径。下面这段纯 C++ 代码不依赖第三方库,可以用来验证齐次坐标变换逻辑;如果作业框架要求用某个线性代数库,把包含路径换成框架实际路径。
#include <cmath> #include <iostream> int main() { // 齐次坐标:点 P=(2,1,1),先逆时针旋转 45 度,再平移 (1,2) const double theta = 45.0 * M_PI / 180.0; double R[3][3] = { {std::cos(theta), -std::sin(theta), 0.0}, {std::sin(theta), std::cos(theta), 0.0}, {0.0, 0.0, 1.0} }; double T[3][3] = { {1.0, 0.0, 1.0}, {0.0, 1.0, 2.0}, {0.0, 0.0, 1.0} }; double P[3] = {2.0, 1.0, 1.0}; double RP[3] = {0.0, 0.0, 0.0}; double TP[3] = {0.0, 0.0, 0.0}; // 先旋转:R * P for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { RP[i] += R[i][j] * P[j]; } } // 再平移:T * (R * P) for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { TP[i] += T[i][j] * RP[j]; } } std::cout << TP[0] << ", " << TP[1] << std::endl; return 0; }这段代码把旋转矩阵和平移矩阵都写成 3x3 齐次形式,先乘旋转再乘平移,顺序不能反。M_PI是圆周率,theta必须用弧度。RP存旋转后的点,TP存最终点。编译时先直接验证:
# 先直接编译,验证代码本身没问题;-I 用来补充头文件搜索路径 g++ -std=c++11 main.cpp -o Transformation # 运行看输出,正常应接近 (1.12, 3.12) ./Transformation-std=c++11指定语言标准,-I后面跟头文件目录,如果框架头文件在include目录下,就写-I./include。运行结果不对时先检查角度有没有转弧度,再检查矩阵乘法顺序。头文件找不到时不要盲装库,先用find /usr/include -name '头文件名'看系统里有没有,再决定是补路径还是装依赖。
5.2 现象:undefined reference to ...
编译能过,链接阶段报undefined reference to,后面跟函数名。根因是函数只有声明没有定义,或者定义在另一个源文件里但构建时没把它加进来。常见做法是检查构建配置里有没有漏源文件,直接编译时把所有用到的.cpp都列出来。如果依赖第三方库,还要补-l和-L。
# 直接把所有源文件列出来,避免链接阶段找不到定义 g++ -std=c++11 main.cpp transform.cpp -o Transformation # 如果依赖某个库,-L 指定库目录,-l 指定库名 g++ -std=c++11 main.cpp -L./lib -l<mylib> -o Transformationmain.cpp和transform.cpp必须一起编译,只编译main.cpp就会在链接时报找不到transform.cpp里的函数。-L./lib告诉链接器去哪里找库文件,-l<mylib>是库名,实际使用时把<mylib>换成真实库名,不需要写lib前缀和扩展名。如果用的是构建配置,检查配置文件里有没有把源文件或库加进去。链接错误不要改代码里的函数名,先看构建命令缺了什么。
5.3 现象:Segmentation fault或Bus error
程序运行时突然报段错误或总线错误,终端只给一行提示,没有行号。根因常见的是数组越界、访问空指针、在栈上开太大的数组、对齐问题。作业0 代码量小,数组越界最好查。解决时打开 core dump,用调试符号重新编译,再用调试器看调用栈。不要靠猜,直接让程序把崩溃位置吐出来。
# 打开 core dump,方便崩溃后看调用栈 ulimit -c unlimited # 用调试符号重新编译,-O0 关闭优化,栈信息更准 g++ -std=c++11 -g -O0 main.cpp -o Transformation # 运行后若崩溃,用调试器看栈 gdb ./Transformationulimit -c unlimited允许生成 core 文件,-g保留调试符号,-O0关闭优化,避免变量被优化掉。进入调试器后先输入run运行,崩溃后输入bt看调用栈。栈里最上面几行就是出错位置。段错误如果是数组越界,检查循环边界和数组长度;如果是栈空间过大,把大数组改成动态分配。总线错误和段错误成因相似,先按同一套流程查。
5.4 现象:Math Error或结果出现nan
程序没崩,但输出nan或者直接报数学错误。根因通常是除数为 0、acos输入超出[-1,1]、三角函数用了角度而不是弧度。作业0 里旋转 45 度,必须先把 45 转成弧度。acos(-1)能得到圆周率,但acos输入超过范围就会返回nan。解决时在数学函数调用前做输入检查。
#include <cmath> #include <iostream> int main() { double angle_deg = 30.0; // C++ 三角函数用弧度,不是角度;这里先转弧度 double angle_rad = angle_deg * M_PI / 180.0; std::cout << std::sin(angle_rad) << std::endl; // acos 的输入必须在 [-1, 1],越界会得到 nan double x = 1.0000001; if (x < -1.0) x = -1.0; if (x > 1.0) x = 1.0; std::cout << std::acos(x) << std::endl; return 0; }angle_deg * M_PI / 180.0是角度转弧度的固定写法,顺序不要写成angle_deg * 180.0 / M_PI。acos前用两个if把输入夹到合法范围,这是最常见的保护写法。如果输出还是nan,检查分母有没有 0,以及浮点数比较有没有用==。数学错误不要先怀疑编译器,先把每个中间结果打印出来。
5.5 现象:构建目录里执行配置命令报找不到配置文件
现象是在终端执行构建配置命令,提示找不到配置文件,或者生成的构建文件不对。根因通常是你不在构建目录里,或者..和.搞反了。..表示上一级目录,.表示当前目录。正确做法是在项目根目录下建build,进build再执行配置,配置命令后面跟..。如果缓存乱了,删掉build重来,不要手动改缓存文件。
# 确认当前目录和上一级目录内容,防止在错误目录执行 pwd ls .. # 删掉旧构建目录重新来,避免缓存导致配置错乱 rm -rf build mkdir build && cd build # 生成构建文件;.. 表示项目根目录,. 表示当前目录,搞反就报找不到配置 cmake .. make # 运行,可执行文件名以构建配置为准 ./Transformationpwd确认当前位置,ls ..看上一级有没有构建配置文件。rm -rf build只删构建目录,不删源码,删之前确认当前不在build里面。cmake ..的..是关键,表示去上一级找配置文件;如果在项目根目录执行cmake .,生成物会散在源码目录里,后面很难清理。make报错会直接显示在终端,先看第一条错误,不要从最后一行开始看。
6. 快速定位:从报错行到根因的排查表和自检习惯
这类环境问题最怕东一榔头西一棒子。我现在的习惯是先分层:宿主机层、虚拟机启动层、系统层、构建层、运行层。每层只取一个证据,不跨层猜。虚拟硬盘打不开,就先看文件大小和路径;启动黑屏,就看虚拟化开关和内存;增强功能失败,就看挂载点和内核头文件;拖放无效,就看模块和双向设置;编译报错,就看构建目录和包含路径;运行崩溃,就看 core 和调用栈。下面这张表是我排查时最常用的对照,先按现象找到第一反应,再执行对应命令。
| 现象 | 先查什么 | 命令或动作 |
|---|---|---|
| 虚拟硬盘打不开 | 文件是否完整、路径是否有中文 | ls -lh、file、挪到纯英文目录 |
| 启动黑屏或报虚拟化不可用 | 宿主机虚拟化开关、可用内存 | free -h、固件设置 |
| 登录后弹回登录界面 | 根分区是否满、是否有异常快照 | df -h /、du -sh |
| 增强功能安装失败 | 光驱挂载点、内核头文件版本 | ls /media/cdrom、uname -r |
| 拖放设置双向仍无效 | 增强功能模块、重启顺序 | lsmod、id、关机再启动 |
| 头文件找不到 | 包含路径、大小写 | g++ -I、find /usr/include |
| 链接错误 | 源文件是否列全、库是否补上 | g++ main.cpp transform.cpp、-l |
| 段错误或总线错误 | core 是否打开、调试符号 | ulimit -c unlimited、gdb后bt |
结果出现nan | 角度转弧度、除数为 0、acos越界 | 打印中间变量、夹紧输入范围 |
这张表不用背,关键是养成“先证据后动作”的顺序。比如看到undefined reference,不要先去改函数名,先看构建命令里有没有漏源文件;看到Segmentation fault,不要先重装虚拟机,先开 core 看栈。每次只改一个变量,改完立刻重跑同一条命令,确认是不是这个原因。最怕一次改五处,最后好了也不知道为什么好。
从那以后我每次配这种作业环境,都强制走一遍“三件套”:文件完整性检查、挂载点检查、构建目录检查。文件完整性看大小和类型,挂载点看光驱和共享目录,构建目录看pwd和上一级有没有配置文件。这三步跑完,再动代码。这份作业0 的虚拟机使用说明和报错对照我也整理在资源里,需要的话从下载页取用,先把虚拟硬盘和增强功能跑通,再去看齐次坐标变换。希望帮到你。
本文还有配套的精品资源,点击获取