报错如下:
Database directory: android12
Lseek failed: Invalid argument
Search complete. Search time = 4.11 seconds.
通过对cscope编译debug,最终发现传入一个特别大的索引数据,导致lseek()把它当成无效参数。
log如下:
find.c, dbseek(), line = 1250, offset = 0, BUFSIZ = 8192, blocknumber = -1
find.c, dbseek(), line = 1261, offset = 0, BUFSIZ = 8192, blocknumber = 0
find.c, dbseek(), offset = 3472328295956396737, BUFSIZ = 8192, blocknumber = 0
find.c, dbseek(), offset = 3472328295956396737, BUFSIZ = 8192, blocknumber = 0, n = 423868200189989
Lseek failed: Invalid argument
从上边看出lseek()传入的offset为:3472328295956396737,初步算下它到底有多大?
3472328295956396737 = 3472328TB,竟然这么大的数据。
开始还以为是lseek()用的32位api导致的,最后即使换成lseek64()的64位api也没啥用,由于主机使4T的硬盘,发现lseek64()最多可以访问8TB内存,如果传入16TB直接报无效参数。
于是写了一个例子验证下
验证sample
//1.lseek64()
//#define _GNU_SOURCE /* for O_DIRECT */
//Or: 2.lseek64()
#define __USE_FILE_OFFSET64
#define __USE_LARGEFILE64
#define _LARGEFILE64_SOURCE
#include <iostream>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include<typeinfo>
#include<climits>
#include <fcntl.h>
#include <sys/types.h>
using namespace std;
int main(int argc,char*argv[]){
//2.lseek 64 bit usage
//long count = 3472328295956396737 = 3472328TB
//4294967295 //4G
//9223372036854775807 = 2^63 -1 (long) : 9223372TB
long count = (1L << 44) - 1;
printf("count = %ld\n",count);
//printf("sizeof(off64_t) = %ld\n",sizeof(off64_t));
// printf("type(off64_t) = %s\n",typeid(off64_t).name()); //off64_t : long
// printf("type(count) = %s\n",typeid(count).name()); //count: long
// printf("type(LONG_MAX) = %s\n",typeid(LONG_MAX).name());
// printf("LONG_MAX = %ld\n",LONG_MAX);
//open
int fd = open(argv[1], O_LARGEFILE | O_RDWR, 0666);
//if(lseek64(STDIN_FILENO, (off64_t)count, 0) == -1)
//lseek64
long size = lseek64(fd, (long)count, 0);
printf("size = %ld\n",size);
if(size == -1)
perror("Lseek failed");
else
printf("seek OK\n");
return 0;
}
最终猜测是cscope.out索引导致的问题,可能超过200GB的代码使用cscope可能就有问题;但是单独用小于200GB的小文件倒是没问题,这其实也算是一种解决办法。
猜测是cscope的bug导致的,因为cscope自从2018年更新到v15.9以后,再也没更新了。
竟然是参数不对导致的,如下优化修改可以解决大工程源码问题。
优化修改/usr/local/bin/cscope-indexer:
<1>.忽略索引prebuilts和out目录
- #find $DIR \( -type f -o -type l \)
+ find $DIR ! -path "./out/*.[c]" ! -path "./out/*x86_64*/*" ! -path "./prebuilts/*" \( -type f -o -type l \)
<2>.修改需要索引的文件
- egrep -i '\.([chly](xx|pp)*|cc|hh|java|cpp|Makefile|mk|aidl|xml|sh|te|rc|bp|dtsi|hal)$' | \
+ egrep -i '\.([ch](xx|pp)*|java|aidl|hal)$' | \
Or
//h、cpp、c
+ egrep -i '\.(h|cpp|c|java|aidl|hal)$' | \
Or
//c、cpp、cxx、cc、h、hc、hxx、hpp
+ egrep -i '\.([ch](c|xx|pp)*|java|aidl|hal)$' | \
注意:同时索引cpp和cc或c和cc导致冲突,无法找到调用函数,这时可以不索引.cc结尾的文件。
如果cscope无法找到该函数可以使用:cscope-find-egrep-pattern命令,不过时间在20s以内。
<3>.修改索引命令(可选)
- cscope -Rqbk -i $LIST_FILE -f $DATABASE_FILE
+ cscope -RqbkuC -i $LIST_FILE -f $DATABASE_FILE
此处不修改也没问题。
感受cscope的强大吧!