./diskimageaccess(diskimageaccess_soln) 运行失败

如果你使用的是ubuntu20.04及以上版本按照assign文档运行该可执行文件大概率会出现error while loading shared libraries: libcrypto.so.1.0.0: cannot open shared object file: No such file or directory这种错误.他告诉你找不到这个共享库
可能有以下几种情况:

  1. 测试中引用了openssl库,你可能没有安装这个库,可使用sudo apt-get install libssl-dev进行安装
  2. 即使你执行上述指令安装了他可能还是会出现错误,因为ubuntu20.04默认安装的版本高于1.0.0.可用openssl version命令查看当前版本.
    综上我们要手动编译这个库
    这里我给出全部命令,按部就班即可,想了解更多可以自行搜索.
wget https://www.openssl.org/source/openssl-1.0.0.tar.gz

tar -vxzf openssl-1.0.0.tar.gz
rm openssl-1.0.0.tar.gz

cd openssl-1.0.0
mkdir build

vim openssl.ld

然后在openssl.ld文件中输入一下内容:

OPENSSL_1.0.0 {
  global:
  *;
};

OPENSSL_1.0.1 {
  new*;
}OPENSSL_1.0.0;

OPENSSL_1.0.1p {
  new*;
}OPENSSL_1.0.0;

然后退出进行编译输入以下命令,最后复制到/usr/lib目录中:

./config no-asm shared -Wl,--version-script=openssl.ld --prefix=./build
make -j`nproc`

sudo cp libcrypto.so.1.0.0 /usr/lib/

参考博客: https://blog.csdn.net/weixin_40837318/article/details/127545368

测试框架代码中的getopt函数

我们先来看看GPT对于该函数的总结:
getopt 函数的原型如下:

int getopt(int argc, char *const argv[], const char *optstring);
  • argc:命令行参数的数量,包括程序名称在内。
  • argv:命令行参数的字符串数组,每个元素是一个参数字符串。
  • optstring:指定可以接受的选项字符集合。
    getopt 函数会依次解析命令行参数,并返回下一个选项字符。如果没有更多选项字符,或者遇到非选项参数,则返回 -1。解析过程中,getopt 函数会自动处理一些常见的选项处理情况,如长选项和参数。

getopt 是一个用于解析命令行参数的函数,它可以帮助我们在程序中处理命令行输入。getopt 函数可以识别和解析命令行中的选项字符,并提供了一种方便的方式来处理这些选项。

getopt 函数的作用主要有以下几个方面:

  1. 解析选项字符:getopt 函数可以识别命令行中的选项字符(通常以---开头),并将其与预定义的选项进行匹配。它可以帮助我们检测哪些选项被指定,并采取相应的操作
  2. 处理选项参数:某些选项可能需要附加参数。getopt 函数可以识别这些选项,并将参数与选项关联起来。通过 optarg 变量,我们可以访问这些选项参数的值,从而在程序中进行进一步处理。
  3. 错误处理:getopt 函数可以处理一些常见的错误情况,如未知选项或缺少必需的参数。它会返回特殊的值,以指示这些错误,并且可以通过 optopt 变量获取有关未知选项的信息。
    上面讲的可能还是比较抽象,现结合代码来深入理解一下这个函数:
    这里给出示例代码:
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
	for(int i = 0; i< argc; i++) {
		printf("%s ",argv[i]);
	}
	puts("");

	int opt,cnt=0;

	while ((opt = getopt(argc, argv, "io")) != -1) {
		cnt++;
		switch (opt) {
			case 'i':
				printf("Input file: %s\n", optarg);
				break;
			case 'o':
				printf("Output file: %s\n", optarg);
				break;
			default:
				printf("Invalid option\n");
				return 1;
		}
	}

	printf("execute getopt cnt: %d\n",cnt);
	printf("optind: %d ,argc: %d\n",optind,argc);

	for(int i = 0; i < argc; i++) {
		printf("%s ",argv[i]);
	}
	puts("");

	// 处理剩余的非选项参数
	for (int i = optind; i < argc; i++) {
		printf("Non-option argument: %s\n", argv[i]);
	}
	return 0;
}

把该源文件编译成可执行文件getoptTest后输入如下指令:

./getoptTest -i input.txt -o output.txt file1 file2

可得到以下输出:

./getoptTest -i input.txt -o output.txt file1 file2 
Input file: (null)
Output file: (null)
success getopt cnt: 2
optind: 3 ,argc: 7
./getoptTest -i -o input.txt output.txt file1 file2 
Non-option argument: input.txt
Non-option argument: output.txt
Non-option argument: file1
Non-option argument: file2

我们可以发现getopt函数成功了两次即对-i -o进行了处理,并且可以观察到处理完所有的可选项后我们传入的命令行参数的顺序发生了变化.可以说明getopt会对命令行参数的顺序进行调整,他会把可选项放在最前面,然后非可选项参数按原来的次序放在可选项的后面.这也可以解释平常我们使用的gcc命令的实现可能就调用了这个函数。
如:

gcc -o test test.c
gcc test -o test.c

这两个命令的效果就相同.
在这个测试中还有提到了optarg, optind参数,对于前者可自行搜索以下,这里主要讲一下optind参数,当你执行完这个循环时(注意这里是整个循环,而不是单个getopt函数,通常我们都使用类似上述的循环来使用该函数,单独调用意义不大).optind为第一个非可选项的命令行参数的索引.听起来可能绕口,看上述例子就比较好理解了(索引从0开始)

测试

测试就比较简单了,最简单粗暴的方式就是把每一个输出重定向到一个文件中,然后用diff和官方的答案进行对比。当然更优雅的方式可以写一个shell脚本实现自动化测试,感觉还是一个比较好的锻炼机会(hhh)