做MIT S6.801时,由于给定的环境中没有strcat函数,所以使用了memmove函数,导致一个字符串变量中的数据被覆盖。
代码的功能为实现一个简单find命令,查找目录下的目标文件的位置。使用递归对子目录进行遍历。
当进入到递归时,发现传入的path参数变成空字符串,所以无法与当前文件名进行比较。
如果改用malloc使用堆内存时,path变量不会变成空字符串。
一开始以为是局部变量作用域消失,但传入的path变量是一个地址,母函数没有运行完前,变量是不会销毁的。所以排除这个可能。
经过调试发现,是memmove中,将de.name内存复制的时候,将de.name后的空白内存复制过去,造成了dir变量的越界,覆盖了dir变量后的path变量的内存。
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
#define BUF_SIZE 14
void find(char *dir,char *path);
char *cutoff(char *path);
int main(int argc, char *argv[]){
if(argc < 2){
exit(-1);
}
char path[BUF_SIZE];
//char * path = (char *)malloc(BUF_SIZE*sizeof(char));
char dir[BUF_SIZE];
strcpy(dir,argv[1]);
strcpy(path,argv[2]);
find(dir,path);
free(path);
exit(0);
}
void find(char *dir, char *path){
int fd;
struct dirent de;
struct stat st;
fd = open(dir,0);
if(fd < 0){
fprintf(2,"open error\n");
return;
}
if(fstat(fd,&st)<0){
fprintf(2,"stat error\n");
close(fd);
exit(1);
}
char *p;
int str_len;
if(!strcmp(dir,"./a/b")){
printf("%d\n",st.type);
}
switch(st.type){
case T_FILE:
p = cutoff(dir);
if(!strcmp(p,path)){
printf("%s%s",dir,path);
}
break;
case T_DIR:
printf("path %s\n",path);
p = dir+strlen(dir);
*p++ = '/';
while((str_len = read(fd,(void *)&de,sizeof(de))) == sizeof(de)){
if(str_len == 0)
return;
if(de.inum == 0)
continue;
if(!strcmp(de.name,".")||!strcmp(de.name,"..")){
continue;
}
//memmove(p,de.name,BUF_SIZE);
memmove(p,de.name,strlen(de.name)+1);
printf("path %s\n",path);
if(!strcmp(de.name,path)){
printf("%s\n",dir);
}
stat(dir,&st);
if(st.type == 1){
find(dir,path);
}
}
break;
}
}
char *cutoff(char *path){
char *p;
for(p = path+strlen(path);p >= path &&*p != '/';p--);
p++;
return p;
}
C语言给了程序员足够的自由,但使用C语言时,还是要十分小心!