c - 如果这是堆溢出导致我的程序崩溃,我应该如何正确处理内存分配?

标签 c debugging memory-management file-io heap-memory

我正在尝试编写一个程序来搜索文件中的模式并用一些子字符串替换它们。本质上,我将修改后的文本写入临时文件,删除原始文件,并将临时文件重命名为原始文件名。我已经在单个文件上进行了测试,一个接一个,看起来效果很好。

下一步是递归地执行操作,当它遍历一些文件并按应有的方式修改它们时,它达到了一个点(在几次调用 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 循环后

关于c - 如果这是堆溢出导致我的程序崩溃,我应该如何正确处理内存分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35472018/

相关文章:

c - 使用二级指针初始化 SequenceList

python - PDB 不会在多线程代码中的断点处停止

java - 我们可以从 java 应用程序内部限制 java 应用程序的内存吗?

java - 我应该使用哪个 Java 集合来实现线程安全缓存?

c - 为什么 make 会重新编译该 makefile 中的所有内容?

c - Malloc 指针数组错误

c++ - 内存转储分析(应用挂起)

java - 如何在 Eclipse Java 程序中找到未运行的代码?

objective-c - 使用 NSOperation 处理目标/ Action 弱引用

c - 符合 MISRA 标准的运行时字节顺序检测