【项目心得】使用C语言写一个Json解析器

本篇博客用以总结在实现Json Tutorial时获得的经验和心得,项目仓库地址json_tutorial

个人认为这个项目还是一个非常适合的入门项目,作者深入浅出地讲解如何从零用C语言实现一个自己的Json解析库。虽然Json解析的算法并不算难,但是项目教程中提到如单元测试等实践中常用的开发方法,以及关于指针的一些陷阱,并且解释了之前困扰我的许多问题,非常适合学习。

程序的编译和链接

在教程的CMake文件中,是这么写的:

1
2
3
add_library(leptjson leptjson.c)
add_executable(tutorial test.c)
target_link_libraries(tutorial leptjson)

其实从字面意思就可以读出大致的意思了,因为我们想编写的只是一个库,所以将leptjson.c这个文件编译为一个leptjson库,最后在构建的项目中可以看到leptjson.a这个静态库,就是编译的结果。

然而我们需要对这个库进行调试,所以还引入了test.c这个单元测试程序,把它编译成一个可执行文件tutorial.exe,同时,因为tutorial需要使用我们的库来测试,所以还要将leptjson库链接到tutorial上,最终形成可执行文件。

之前一直搞不懂C/C++的项目是如何构建的,现在大致明白了。头文件仅仅是提供函数、类的声明,而源文件才是提供定义的。所以只有源文件需要进行编译,而头文件不用。将源文件编译后,与库文件链接到一起,就形成了可执行文件。

单元测试

之前在写代码的时候,往往是在main函数中写一些简单的代码用于测试程序的结果,或是使用printf等打印函数来检查变量的值,这样的方法在大型项目的开发中会遇到许多困难。所以作者在这个项目中使用了**单元测试(Unit Test)**的方法来确保程序开发的准确性。

软件开发的周期,一般是提出一个需求后,编写代码,再编写单元测试,看代码是否通过测试。然而也有一种测试驱动开发(test-driven development, TDD),是先编写单元测试,验证原来的程序不能通过通过测试,再编写代码使其通过测试。

本项目自行编写了一个极简的单元测试框架,每次运行会输出单元测试的通过个数,以及通过率。代码过于冗长,就不进行解析了,在之后学习单元测试的有关框架后,再编写一篇博客进行记录。

断言

断言的语法:

1
2
#include <assert.h>
assert(cond);

断言语句仅在debug状态下会生效。当cond的结果为假时,程序会崩溃,并输出相关的信息。那么,要在何时使用断言,何时抛出异常呢?当一个错误是由程序员的编写代码失误导致时,就使用断言;当一个错误是程序员无法预期的(如网络、文件异常)时,就要使用异常处理。

另一个要注意的事,不要在断言中改变变量的值,这可能导致debug版本和release版本的程序行为不一致。

内存泄漏检测

使用Visual Studio进行编程时可以在代码中嵌入一些语句来实现,但是我更喜欢使用Clion,所以这里介绍另一种方法:Valgrind。

Valgrind仅在Linux和macOS上可以使用,但是在Windows上,我们也可以使用**WSL(Windows Subsystem for Linux)**来完成。安装WSL后,在命令行安装Valgrind,然后在Clion中设置好toolchain和CMake,运行时点击右上方run xxx with Valgrind Memcheck即可,当发生内存泄漏时,Clion的debug窗口会进行提示,并显示调用栈。

悬挂指针问题

在tutorial5中,作者提到了一个难以察觉的bug:

1
2
3
4
5
6
7
8
9
for (;;) {
/* bug! */
lept_value* e = lept_context_push(c, sizeof(lept_value));
lept_init(e);
size++;
if ((ret = lept_parse_value(c, e)) != LEPT_PARSE_OK)
return ret;
/* ... */
}

在这里,先获得了栈中的一个位置的指针e,以供写入解析后的值。但是在lept_parse_value后,栈的大小可能会变大,此时栈会调用realloc重新分配内存,所以原来的内存就失效了,导致指针e指向的内容也失效了。

在C++的容器中也会遇到类似的问题,当我们获得了一个容器的指针或迭代器后,如果在指针的生存周期内,容器发生了内存的重新分配,则原先指针指向的内容很可能会失效。所以在编程时,一定要清楚变量,特别是指针的生存周期。


【项目心得】使用C语言写一个Json解析器
http://zhouhf.top/2024/10/11/Json-Parser/
作者
周洪锋
发布于
2024年10月11日
许可协议