c - sqlite3_bind_text段错误

标签 c

我的应用程序对给定目录进行递归扫描,我将每个唯一路径存储在数据库中。 有一次我遇到了段错误并且 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(由调用者分配)被删除了两次。即使使用 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

最佳答案

您的xrealloc call ( xrealloc(baseName, buflen << 1); ) 是错误的:您没有将其结果分配给 baseNamexrealloc可能会释放你给它的缓冲区(并返回一个不同的指针),所以如果你不分配结果,那么你可能会双重释放缓冲区。

关于c - sqlite3_bind_text段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12504508/

相关文章:

c - 在 STDOUT 和 STDIN 的文件描述符上执行库函数的奇怪行为

c - 为什么 GCC 允许可变大小数组的静态内存分配?

c - 如何使宏返回字符而不是字符串?

c++ - C 标识符名称 : What goes with which compiler?

c - 如何在 C99 中声明另一个文件中定义的全局数组大小?

更改 scanf() 分隔符

c - Libav(ffmpeg)容器编解码器时基和流时基的目的是什么?

c - 多个进程写入同一个文件(C)

c - 改进 Makefile,使其仅创建和清理已更改/特别请求的程序

c - Autotools库中没有符号