CMU15-445 2022 Fall 通关记录 —— Project 0: Trie Tree

Project 0

Project #0 - C++ Primer | CMU 15-445/645 :: Intro to Database Systems (Fall 2022) — 项目 #0 - C++ 入门 | CMU 15-445/645 :: 数据库系统简介(2022 年秋季)

前期准备

为完成该项目做的一些准备:

  • 创建个人项目FarewellYi/BusTub-private: My CMU 15-445 2022 Fall course homework (github.com)

  • clone到本地,并pull 2022 Fall的原BusTubcmu-db/bustub at v20221128-2022fall (github.com)

    期间遇到main和master分支不兼容的问题,于是删除已拉取的BusTub-private并重新拉取master版本;

    可以使用如下命令拉取2022Fall版本:

    git clone --branch v20221128-2022fall https://github.com/cmu-db/bustub.git
    

    但是如果按照BusTub的如下说明:

    image-20230530095035653

    相当于把本地仓库连接到远程的bustub下,本地会自动更新为最新的commit版本(大概,由于我也不是很会用git,缺点暴露);

    于是我只能重新拉取个人仓库中的2022Fall版本,就此正式开始我的通关之旅。

  • 编译BusTub环境

    期间遇到无法安装clang-14依赖的问题

    • 尝试更新软件包,并通过llvm密钥配置下载路径,但遇到众多依赖包版本不匹配的问题

    • 尝试从llvm下载二进制源码并置为环境变量,但是貌似并没有被主机识别到

    • 根据stack overflow上的某位回答,ubuntu18.04版本默认不支持clang-14,可以考虑将系统更新至20.04或者22.04版本,由于本人使用的环境是虚拟机,影响也不大,所以将系统备份后更新至20.04版本

      经验证,重启后依旧无法直接通过bustub提供的packages脚本完成所有package的依赖安装

      在Ubuntu上配置clang-14的环境_5436649486的博客-CSDN博客

      根据上面这位博主的建议,通过wget获取llvm的软件包,再按照BusTub中Readme的步骤,则不会出现依赖不匹配的问题

  • 按照BusTub Readme中的说明,build 项目,最终使用以下命令

    $ cd build
    $ make check-tests
    

    检查环境的搭建情况(虽然本意并非如此,而是检查各个模块的完成情况的)

  • 拟采用VS Code + SSH 本地虚拟机的方式完成本项目,有关如何配置VSCode,可以参考下面这篇文章

    CMU 15445 vscode/clion clang12 cmake环境配置 - 知乎 (zhihu.com)

    由于2022 Fall中要求的使用clang-14完成编译,因此我的工具选择的是下图中底部蓝框所示的clang-14;

    安装cmake后,可以使用CMakeLists.txt或者是选择底部蓝框右边的bulid完成构建,其中使用到的编译选项如图中蓝框所示,各选项的含义如下:

     /usr/bin/cmake --no-warn-unused-cli 
     -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE 
     -DCMAKE_BUILD_TYPE:STRING=Debug            		// Debug模式, Release模式Debug改Release即可
     -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/clang-12  	// 编译器路径,不指定默认gnu /usr/bin/gcc
     -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++-12  // 同上 默认/usr/bin/g++
     -S/home/wxx/bustub                     			// 要构建的cmake项目根目录 
     -B/home/wxx/bustub/build                			// 构建目标目录   
     -G "Unix Makefiles"                     			// 生成器 generators
    

    image-20230530103323990

    CMake时遇到四个警告,如下图所示:

    image-20230530105044690

    且不论第一个,因为即使默认选用clang12,但是并不影响编译;后面三个警告的意思就是没有找到这些包,以下是这些包的作用:

    1. clang-format:clang-format是一个用于代码格式化的工具。它基于一组配置规则,可以自动调整源代码的排版和格式,使其符合统一的风格和标准。使用clang-format可以帮助团队在代码库中保持一致的代码风格,提高代码的可读性和维护性。
    2. clang-tidy:clang-tidy是一个静态分析工具,用于检查C++代码中的潜在问题和常见错误。它基于一系列的检查器(checks),可以对代码进行静态分析,并给出相关的警告或建议。clang-tidy可以帮助开发者发现潜在的bug、不良的编码实践和可改进的代码片段,从而提高代码质量和可靠性(强大的工具,虽然有时有种矫枉过正的感觉)。
    3. clang-apply-replacements:clang-apply-replacements是一个用于应用由clang-tidy或其他工具生成的修复建议的工具。当clang-tidy检测到问题并给出修复建议时,这些建议通常以修复补丁(replacements)的形式提供。clang-apply-replacements可以接收这些修复补丁,并将其应用到源代码文件中,实现自动修复。

    使用常规的装包命令装一下,重启窗口,这些警告就不复存在了。

  • 拟计划采用VSCode在Windows端远程虚拟机完成编码,在Ubuntu端通过CLion完成独立test的调试


本项目的main target 是使用C++17完成一个Trie类,分为以下两个部分

TASK #1:Templated Trie

可以看到源文件中给出了三个类

image-20230530110836081

说明也给的很清楚(这一点太强了,通过注释引导学生,就不会有从零开始的那种望而生畏感)。

官方文档关于如何做,一步一步写的都很清楚(一步一步坐下来只会有种爽快感)。

而且通过此次测试,才发现clang这个工具的强大。

本课的测试代码皆使用Google Test进行编写,在Clion环境中,可以进行每个Task的单元测试,如下图所示:

image-20230530200108767

原本在函数TrieNodeInsertTest前还会有一个前缀DISABLED_,删去即可测试。

在VS Code中,看网上其他人的博客,完成整个Task之后才可以进行测试,根据下图,可以看出该Task一共有五个测试单元:

image-20230530195138526

执行下面代码即可单独测试该Task:

$ cd build
$ make starter_trie_test
$ ./test/starter_trie_test

经我的实验,修改DISABLED_选项后,重新编译该测试脚本,即可完成不同单元的测试。当我完成Task1之后,关闭了最后一个ConcurrentTest1,测试结果如下:

image-20230530201236502

所以使用VSCode测试也没有那么网上其他人说的那么麻烦。

此处有一点我要说明,我在实现Trie类中的Insert函数时,说明中有一点,当插入的key对应的最后一个结点是TrieNode时,应当修改为TrieNodeWithValue,当我使用make_unique构造TrieNodeWithValue时,调用的构造函数如下所示:

TrieNodeWithValue(TrieNode &&trieNode, T value);

我一开始使用的语句是:

std::make_unique<TrieNodeWithValue<T>>(std::move((*cur).get()), value);

因为文档中有提示,说使用std:unique_prt<TrieNode>* ,即一个指向unique_ptr对象的指针,可以一定程度上避免拷贝的问题,因此上文中的cur对应一个指向unique_ptr对象的指针,解引用后则是unique_ptr对象,我起初向使用get方法获取unique_ptr管理的原对象,但是忘记了此处获取的是指针而非TrieNode,导致编译报错,理应如下:

std::make_unique<TrieNodeWithValue<T>>(std::move(*((*cur).get())), value);

这样写是没错的,但是clang-tidy会提示存在冗余,因此可以依赖clang修复为如下所示:

std::make_unique<TrieNodeWithValue<T>>(std::move(*(*cur)), value);

TASK #2:Concurrent Trie

可以使用Trie类中提供的读写锁ReaderWriterLatch latch_来完成加锁


经过语法检查(所幸平时我的代码风格就是google的风格,在clang的帮助下,也是可以即使排查出它认为的不合理之处),首次提交到gradescope后,提示错误如下图所示:

image-20230530220343029

之后所有的测试用例都是红框中所示的问题。

经过一番检查后,问题在于TrieNodeWithValue类的某个构造函数中,忘记用列表初始化构造父类TrieNode(这个错误在本地测试的时候竟然没有被检查出来)

修改后二次上传,最终百分之百通过,如下图所示:

image-20230530221755983

猜你喜欢

转载自blog.csdn.net/qq_41205665/article/details/131104875