2012-09-20 21 views
0

我的應用程序執行給定目錄的遞歸掃描,我將每個唯一路徑存儲在數據庫中。 在一個點上,我收到了段錯誤和glibc火災:Sqlite3_bind_text分段錯誤

*** 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(由調用者分配)被刪除了兩次:

問題調用下面的功能時,會發生。即使使用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 
+0

你有關於pointe類型不匹配的編譯器警告嗎? –

+0

根本沒有警告 – oliviern

+0

你怎麼知道這個populatePathDB()函數是被指責的?你有沒有堆棧跟蹤? –

回答

1

xrealloc調用(xrealloc(baseName, buflen << 1);)是錯誤的:你是不是對baseName賦予它的結果。 xrealloc可能會釋放你給它的緩衝區(並返回一個不同的指針),所以如果你不分配結果,那麼你可以釋放緩衝區。

+0

非常感謝您的回答。我已經修復了這個bug並想分享它,但是你比我快得多:) – oliviern