实验常见问题
通用问题
- 实现代码的正确性和风格将如何评分?
以下是一些指导原则:
- 复杂的代码段应在注释中加以说明,使读者更容易理解——但不要对简单琐碎的内容过度注释。
- 通用的、可复用的功能应拆分为辅助函数,以避免重复代码——但也不要过度拆分,例如导致执行流程难以理解。
- 代码应使用一致的命名规范,不应包含被注释掉的代码或调试残留。
- 请检查所有可能出错的函数的返回值,并妥善处理这些错误。抛出异常是一种处理不可恢复错误的优雅方式。
- 避免内存错误和泄漏、严重的性能问题(例如无缘无故地分配大量内存)或不必要的复杂方法(例如使用一个复杂的数据结构,但仅比简单方法或使用 C++ 标准库中现成的方案略微高效一点)。
- 在报告中,我们希望看到你认真地考虑了可用的实现策略(例如数据结构的选择),并能够合理解释你所做出的选择。
- 在提交每次作业之前,请运行
cmake --build build --target format(以统一代码格式),并确保删除起始代码中包含的任何占位代码或注释。 - 另外(可选)运行
cmake --build build --target tidy以获取关于 C++ 编程实践的改进建议。
- 如何运行单个测试?
- 如何打印调试信息并使其与测试步骤一起整齐地显示?
- 可以在头文件中添加 include 语句吗?
- 如何使用
git? - 运行
$ git clone [bundle name] [unbundled name]。 cd进入解压后的目录。- 运行
$ git log并确认能看到你期望的提交记录。 - 复制起始代码提交的 commit hash。
- 运行
$ git diff [hash]以确认能看到你想提交的所有更改。 - 如何调试?
- 安装
gdb(在虚拟机上,sudo apt-get install gdb)。 - 在
build目录中启动gdb,加载你想调试的测试对应的可执行文件(ls tests可以查看可执行文件列表)。例如在 build 目录中运行:gdb tests/byte_stream_one_write。 - 测试失败的输出会显示失败的那部分测试。要在该部分设置断点,请在测试文件中对应测试用例创建的行上设置断点。测试源代码位于
minnow/tests(而不是minnow/build/tests)。例如,如果你在byte_stream_one_write中write-pop2-end测试失败,break 83(即write-pop2-end测试用例创建的位置)。 - 你可以像往常一样使用函数名在自定义函数上设置断点。
- 我们不建议修改
util目录中的任何文件,因为弄坏支持库会使调试变得困难。 - 如果测试超时,但你想检查在没有超时限制的情况下是否能通过,可以单独运行测试可执行文件,这样不会强制执行超时。例如在 build 目录中运行:
./tests/byte_stream_one_write。 gdb可以帮助调试超时问题。在gdb中运行测试时,如果程序看起来卡住了(可能正在执行较慢的代码段),按 ctrl-C 然后 backtrace 来暂停并查看正在执行的代码。
将环境变量 TEST_ONLY 设置为测试的确切名称。例如,如果目标测试名为 "write, close, read",则运行命令
export TEST_ONLY="write, close, read"
。
然后照常运行 cmake --build build --target test。此时只会运行指定的测试。你可以通过运行
unset TEST_ONLY 来恢复原始行为。
包含 "debug.hh" 头文件,并使用 debug() 函数。该函数支持字符串插值。例如:
debug( "About to pop {} bytes", len );
可以,但请不要更改任何类的公共接口。
以下是一些学习 Git 的资源。
简要概述:Git 提交会保存代码当前状态的快照。例如,假设你破坏了一个你知道以前能正常工作的功能,但不确定是哪段代码导致了问题。如果你在功能正常时做了一次提交,就可以检出那次提交,查看一切还正常工作时的代码状态。所以,每次实现功能后都应该提交!提交步骤如下:
首先,git add 你修改过的文件——每次提交前都需要 add。例如 git add ./src/byte_stream.*
然后,用一条描述代码当前状态的信息提交。例如 git commit -m "All tests pass except many_writes times out."
你可以通过运行 git status 查看修改了哪些文件。要深入了解 Git 仓库的状态,命令行工具 tig 或图形化工具 gitk 都非常有帮助。
一个提交所有修改文件的快捷方式是 git commit -am "[提交信息]"。
实际检查:如果你想验证自己确实提交了预期的文件,以下方法可能有用。
首先,提交后运行 git status。你应该看到 nothing to commit, working tree clean 的提示。如果有未提交的更改,你会看到:Changes not staged for commit:。
其次,在将 git bundle 复制到 rice 服务器并登录 rice 后:
上面关于运行单个测试的技巧以及 debug() 函数都是很好的入门方式。除此之外,gdb 是调试实验的强大工具!如果你需要复习,可以参考 CS107 指南。
使用 gdb 调试测试的步骤:
实验 0
- 如果调用者尝试以大于可用长度的
len进行 pop,程序应该如何处理?
对于调用者尝试弹出超过流中缓冲量的情况,我们没有任何偏好,只要你合理处理且不会崩溃即可。如果你想弹出最大可用量,我们认可。如果你想抛出异常,我们也认可。
- 代码需要多快? 一个合理的参考标准是:如果任何测试耗时超过 2 秒,那可能值得继续探索其他表示 ByteStream 的方式。如果测试末尾的基准测试结果低于 0.1 Gbit/s(每秒 1 亿比特),这也是一个需要重新考虑设计的信号。本实验不需要复杂的数据结构,但可能仍需要一些试错才能找到合理的方案。有时候"大 O"分析可能会误导真实程序的性能评估——常数因子可能非常重要!