Realloc把代码搞乱了

Realloc把代码搞乱了,c,C,我写了一个程序,应该在一个文件中进行查找和替换,条件是新词必须比旧词长。我对它有很多问题,比如打印奇怪的字符,或者转储内核,但是当我删除realloc语句时,问题似乎就消失了。我不太熟悉这个函数,我犯了什么错误 还有,我的空闲时间应该在哪里 void replace_word(const char *s, const char *old_word, const char *new_word){ char *buffer = malloc(BUFFER_SIZE); char *i

我写了一个程序,应该在一个文件中进行查找和替换,条件是新词必须比旧词长。我对它有很多问题,比如打印奇怪的字符,或者转储内核,但是当我删除
realloc
语句时,问题似乎就消失了。我不太熟悉这个函数,我犯了什么错误

还有,我的空闲时间应该在哪里

void replace_word(const char *s, const char *old_word, const char *new_word){
    char *buffer = malloc(BUFFER_SIZE);
    char *init = buffer;
    FILE *original_file;
    FILE *copy;

    if((original_file = fopen(s, "r")) == NULL){
        perror(s);
        exit(EXIT_FAILURE);
    }

    if((copy = fopen("copy.txt", "w")) == NULL){
        perror("text");
        exit(EXIT_FAILURE);
    }

    int old_word_len = strlen(old_word);
    int new_word_len = strlen(new_word);

    char *src;
    char *dst;
    char *tmp;
    while(fgets(buffer, BUFFER_SIZE, original_file)){
        if((tmp = strstr(buffer, old_word))){
            buffer = realloc(buffer, BUFFER_SIZE + new_word_len - old_word_len);
            src = tmp + old_word_len;
            dst = tmp + new_word_len;
            memmove(dst, src, strlen(src));
            memcpy(tmp, new_word, new_word_len);
            buffer = init;
        }
        fprintf(copy, "%s", buffer);
        if(!strchr(buffer, '\n')){
            fseek(original_file, -old_word_len, SEEK_CUR);
        }
        free(buffer);
        buffer = malloc(BUFFER_SIZE);
    }
    free(buffer);
}

realloc
获取指向动态分配内存的指针,并调整内存块的大小。缺乏动态内存经验的人经常忽略的一点是,
realloc
返回的指针可能与传入的指针不同(通常不是)。通常,堆没有足够的连续内存来执行请求的扩展,因此它会找到一个足够大的新内存块来容纳它,并将以前的内容复制到内存中

关于您的代码,我注意到的第一件事是您执行了一个不安全的
realloc

buffer = realloc(buffer, BUFFER_SIZE + new_word_len - old_word_len);
通过将指针分配到自己的
realloc
,操作系统可能无法完成分配并返回
NULL
。如果发生这种情况,您将丢失指向旧内存的指针,并且您的手上存在内存泄漏。要正确地
realloc
(我猜您无论如何都需要这样做来修正我的下一点),请将
realloc
的结果分配给另一个指针,确认它不是
NULL
,然后覆盖指针

但我认为您的代码的主要问题在于:

buffer = init;

如果我理解正确,此语句的目的是将
buffer
返回到字符串的开头。但是,
init
指向的内存已被
realloc
释放,您最终取消了对悬挂指针的引用。您需要存储一个引用,指向由
realloc

src=tmp+old\u word\n返回的新内存的开头
tmp
指向地址的点是
realloc
memmove(dst、src、strlen(src))之前的地址-->
memmove(dst、src、strlen(src)+1)
buffer=init
init
是旧的缓冲区。您不能使用指向重新分配的空间的任何指针(即使realloc恰好指向同一位置)。这里最好使用整数偏移量。问题是,您假设一旦您执行realloc,tmp将保持有效,而这可能不是。谢谢。它最终似乎起作用了,我所做的是在
if
中创建第二个指针,并使用
malloc
而不是
realloc
,然后将旧的缓冲区复制到其中。我不确定realloc是否会扩展当前的块或创建一个新的块,文档也不清楚。这个解决方案可能很好
realloc
根据旧指针上有多少连续内存可用,展开或创建一个新指针。如果必须创建新块,它会将旧块中的所有内容复制到新块的开头。