私のアプリは特定のディレクトリを再帰的にスキャンし、それぞれの一意のパスをデータベースに保存します。ある時点で、segfault が発生し、glibc が起動します。
*** glibc detected *** ./test: double free or corruption (!prev): 0x08cd1a20 ***
gdb はそれを確認します。
以下の関数を呼び出すと、問題が発生します。
int
populatePathDB(sqlite3* db, char *absolutePath)
{
char *sql;
sqlite3_stmt *stmt ;
int ret;
sql = "INSERT INTO paths (path) VALUES (?)";
ret = sqlite3_prepare_v2(db,sql,-1,&stmt,NULL);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
ret = sqlite3_bind_text(stmt, 1, absolutePath, -1, SQLITE_STATIC);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
sqlite3_step(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
/* sqlite3_clear_bindings(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
sqlite3_reset(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db)); */
ret = sqlite3_finalize( stmt );
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
return SQLITE_OK;
}
変数absolutePath(呼び出し元によって割り当てられた)が2回削除されたと思います。SQLITE_TRANSIENT を使用しても、同じ障害が発生しました。
何か案は?
再帰スキャン機能の追加:
int walkDir( char *dir, unsigned int recursive)
{
DIR* dirstream;
struct stat statbuf;
struct dirent *entry = NULL;
int exists, fd;
size_t dlen, entlen, nlen;
size_t buflen = 0;
char *baseName = NULL;
extern sqlite3 *magicDB_g;
extern sqlite3 *pathDB_g;
assert (dir !=NULL);
if ( ( dirstream = opendir(dir) ) == NULL ) {
ERR_MSG("opendir");
return (EXIT_FAILURE);
}
dlen = strlen(dir);
buflen = MEMCHUNK;
if (dlen >= buflen)
buflen = roundToNextPowerOf2(dlen);
baseName = xmalloc(buflen);
while ( ( entry = readdir(dirstream) ) ) {
if(!strcmp(".",entry->d_name) ||
! strcmp("..",entry->d_name))
continue;
if (entry->d_name[0] == '.')
continue;
nlen = dlen + (entlen = strlen(entry->d_name));
if (unlikely(nlen + 2 > buflen) )
xrealloc(baseName, buflen << 1);
if (dlen == 1 && *dir == '/' )
sprintf(baseName, "%s%s" , dir, entry->d_name);
else
sprintf(baseName, "%s/%s" , dir, entry->d_name);
/*snprintf (baseName, need + 2,"%s/%s", baseName, entry->d_name);*/
exists = lstat(baseName, &statbuf);
if (exists < 0)
continue;
if ( S_ISREG(statbuf.st_mode) && statbuf.st_size != 0 )
{
if ((fd = open(baseName, O_RDONLY)) == -1) {
ERR_MSG("open");
continue;
}
//fileSignature_v1(fd,NBYTES,magicDB_g);
if ( close(fd) == -1)
ERR_MSG("close");
}
if ( S_ISDIR(statbuf.st_mode) )
{
/* Create a absolute path database with unique entries */
populatePathDB(pathDB_g, baseName); <-- No segfault if not called.
if (recursive) {
printf("basename: %s\n",baseName);
walkDir(baseName,recursive);
}
}
}
free(baseName); <-- Seems to be deleted twice when back from populatePathDB()
if (closedir(dirstream) == -1)
ERR_MSG("closedir");
return (EXIT_SUCCESS);
}
エラーステートメントは次のとおりです。
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x379440, bytes=34) at malloc.c:3598
3598 malloc.c: Aucun fichier ou dossier de ce type.
(gdb) bt
#0 _int_malloc (av=0x379440, bytes=34) at malloc.c:3598
#1 0x0024fd3c in __GI___libc_malloc (bytes=34) at malloc.c:2924
#2 0x0011541f in local_strdup (s=0xb7fe2a8c "/lib/i386-linux-gnu/libgcc_s.so.1") at dl-load.c:162
#3 0x001185d4 in _dl_map_object (loader=<optimized out>, name=<optimized out>, type=2, trace_mode=0, mode=-1879048191, nsid=0) at dl-load.c:2473
#4 0x00122d5d in dl_open_worker (a=0xbfffe690) at dl-open.c:225
#5 0x0011ecbf in _dl_catch_error (objname=0xbfffe6b4, errstring=0xbfffe6b8, mallocedp=0xbfffe6bf, operate=0x122c30 <dl_open_worker>, args=0xbfffe690)
at dl-error.c:178
#6 0x001227e4 in _dl_open (file=0x334345 "libgcc_s.so.1", mode=-2147483647, caller_dlopen=0x2d7e38, nsid=-2, argc=2, argv=0xbffff314, env=0x8051040)
at dl-open.c:639
#7 0x002fbd41 in do_dlopen (ptr=0xbfffe840) at dl-libc.c:89
#8 0x0011ecbf in _dl_catch_error (objname=0xbfffe814, errstring=0xbfffe818, mallocedp=0xbfffe81f, operate=0x2fbce0 <do_dlopen>, args=0xbfffe840)
at dl-error.c:178
#9 0x002fbe37 in dlerror_run (operate=<optimized out>, args=<optimized out>) at dl-libc.c:48
#10 0x002fbec7 in __GI___libc_dlopen_mode (name=0x334345 "libgcc_s.so.1", mode=-2147483647) at dl-libc.c:165
#11 0x002d7e38 in init () at ../sysdeps/i386/backtrace.c:44
#12 0x00388e8e in pthread_once () at ../nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S:122
#13 0x002d80a5 in __GI___backtrace (array=0xbfffee90, size=64) at ../sysdeps/i386/backtrace.c:121
#14 0x00241310 in __libc_message (do_abort=2, fmt=0x3393bc "*** glibc detected *** %s: %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:180
#15 0x0024be42 in malloc_printerr (action=<optimized out>, str=<optimized out>, ptr=0x80c4eb8) at malloc.c:5007
#16 0x0804aa8f in walkDir (dir=0x8075a60 "/home/olivier/Téléchargements", recursive=1) at dirtraverser.c:251
#17 0x0804aa63 in walkDir (dir=0x80528f8 "/home/olivier", recursive=1) at dirtraverser.c:245
#18 0x0804bdc0 in main (argc=2, argv=0xbffff314) at main.c:246