Closed. This question is off-topic。它当前不接受答案。
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            想改善这个问题吗? Update the question,所以它是on-topic,用于堆栈溢出。
                        
                        3年前关闭。
                                                                                            
                
        
我正在尝试编写一个程序,该程序搜索文件中的模式并将其替换为一些子字符串。本质上,我将修改后的文本写入临时文件,删除原始文件,然后将临时文件重命名为原始文件名。我已经在单个文件上进行了逐一测试,这似乎工作正常。

下一步是递归执行操作,虽然它遍历了一些文件,并按应有的方式对其进行了修改,但到达某个点(在几次调用replaceline()之后),我得到了这个错误。

*** Error in `/someplace/a.out': double free or corruption (top): 0x0000000000614090 ***


所以我想检查一下gdb中的内容,而我很难理解:

Program received signal SIGABRT, Aborted.
0x00007ffff7a4bcc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56      ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) backtrace
#0  0x00007ffff7a4bcc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff7a4f0d8 in __GI_abort () at abort.c:89
#2  0x00007ffff7a88394 in __libc_message (do_abort=do_abort@entry=1,
    fmt=fmt@entry=0x7ffff7b96b28 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007ffff7a9466e in malloc_printerr (ptr=<optimized out>,
    str=0x7ffff7b96c38 "double free or corruption (top)", action=1) at malloc.c:4996
#4  _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3840
#5  0x00007ffff7a82ae5 in _IO_new_fclose (fp=0x614090) at iofclose.c:85
#6  0x0000000000400fa8 in replaceline (path=0x7fffffffdff0 "./toast/toast3/tt", patternoo=0x401357 "dime",
    replacearoo=0x401352 "lime") at testrep7.c:91
#7  0x00000000004011c5 in recursiveWalk (pathName=0x7fffffffe440 "./toast/toast3", level=1) at testrep7.c:129
#8  0x000000000040118a in recursiveWalk (pathName=0x40135c "./toast", level=0) at testrep7.c:125
#9  0x000000000040122c in main (argc=2, argv=0x7fffffffe958) at testrep7.c:139
(gdb) frame 2
#2  0x00007ffff7a88394 in __libc_message (do_abort=do_abort@entry=1,
    fmt=fmt@entry=0x7ffff7b96b28 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
175     ../sysdeps/posix/libc_fatal.c: No such file or directory.


我知道这与不良的内存分配或不释放某些指针有关?如果是这样,谁能指出我应该在哪里做?

还有可能我多次删除文件吗?这就是我从“双重自由腐败”的含义中得到的意思。

据我所知,我的递归遍历运行良好,因为它精确输出了我想要在replaceline()中使用的路径。

我决定包括整个代码,以防万一该错误与replaceline()以外的内容有关,尽管我确实认为这是出错的地方。很抱歉,如果代码太多,但是我不能完全确定我已设法将问题定位到某些功能。谢谢。

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <libgen.h>

int delete(char* file){

    int status;
    status = remove(file);
}

void renamefile(char* old, char* new){
   int ret;

   ret = rename(old, new);

   if(ret == 0) {
      printf("%s renamed to %s\n", old, new);
   }
   else {
      printf("Error: unable to rename %s\n", old);
        printf("NO %s", strerror(EACCES));
   }
}


char *replace_str(char *str, char *orig, char *rep)
{
  static char buffer[4096];
  char *p;

  if(!(p = strstr(str, orig)))
    return str;

  strncpy(buffer, str, p-str);
  buffer[p-str] = '\0';

  sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));

  return buffer;
}


void replaceline(char* path, char* patternoo, char* replacearoo){

    char buff[BUFSIZ];      // the input line
    char newbuff[BUFSIZ];   // the results of any editing

   char pattern[200];
    strcpy(pattern, patternoo);

   char replace[200];
    strcpy(replace, replacearoo);

    FILE *in, *out;
     char newstr[200];


    //getbases
    char basec[200];
    char dname[200];
    int found = 0;

    strcpy(basec, path);
    strcpy(dname, dirname(basec));

    strcat(dname, "/loot");

    in = fopen( path, "r" );
    out= fopen( dname, "w" );

    while ( fgets( buff, BUFSIZ, in ) != NULL ) {
        if ( strstr( buff, pattern ) != NULL ) {

             //THIS IS WHERE WE DO THE THING
                strcpy(newbuff, replace_str(buff, pattern, strcat(replace,pattern)));
              found = 1;

        } else {
              strcpy( newbuff, buff );
              printf("nothin to do\n");
        }
        fputs( newbuff, out );
            fclose( in );
            fclose( out );
            delete(path); // delete original
            renamefile(dname, path); //the temp is now new
    }

    if(found == 0){
    fclose( in );
    fclose( out );
    }
}

void recursiveWalk(const char *pathName, int level) {
   DIR *dir;
   struct dirent *entry;

   if (!(dir = opendir(pathName))) {
      fprintf(stderr, "Could not open directory\n");
      return;
   }

   if (!(entry = readdir(dir))) {
      fprintf(stderr, "Could not read directory\n");
      return;
   }

   do {
      char path[1024];
      int len = snprintf(path, sizeof(path)-1, "%s/%s", pathName, entry->d_name); // get depth
      if (entry->d_type == DT_DIR) { // found subdirectory
         // skip hidden paths
         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
         }
         recursiveWalk(path, level + 1);
      }
      else { // files
         fprintf(stdout, "%s \n", path); // HERE!!!!!!!!!!!
            replaceline(path,"dime", "lime");
      }
   } while ((entry = readdir(dir)));

   closedir(dir);
}

int main(int argc, char* argv[]){

//  replaceline("./toast/nodime","dime", "lime");
    recursiveWalk("./toast", 0);

    return 0;
}

最佳答案

在功能上:replaceline()

我怀疑代码正在关闭文件,并尽早删除源文件。

建议循环读/修改/写,直到文件结尾,

然后关闭文件并删除源文件。

如果文件包含要替换的字符串,则循环中的后续遍历将尝试从关闭的文件中读取。

建议在读取完整个文件后才关闭,删除,重命名文件。退出while循环后

08-25 01:57