You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言修改缓冲区大小拷贝文件的计时异常及代码优化咨询

你的文件拷贝计时异常与代码问题全解析

一、先解决你最困惑的三个初始问题

1. 为什么首次拷贝后耗时几乎为0?

这是文件指针位置和文件名拼写错误共同导致的:

  • 你在循环外只打开了一次源文件fichier1,第一次拷贝完成后,文件的读指针已经走到了末尾,后续调用read()直接返回0,拷贝循环根本没执行,自然耗时趋近于0。
  • 代码里你创建的目标文件是grosfichier_copy,但删除的是grosfichier_copie(拼写差了一个字母),导致后续循环里目标文件其实是已经写完的旧文件,进一步加剧了异常。

2. free的使用是否正确?

你的free操作是对的!循环里用realloc更新buffer后,temp_buffer和buffer指向同一块内存,所以最后只需要free(buffer)就足够了——你注释掉free(temp_buffer)是正确的,要是提前free反而会触发double free错误。

3. 缓冲区传递给copy函数的方式恰当吗?

完全不恰当,这里有两个致命错误:

// 你的初始copy函数代码
while ((t = read(in, &buffer, sizeof taille))> 0)
    write (out, &buffer, t);
  • &buffer传递的是缓冲区指针的地址,不是缓冲区本身的地址,read会把数据写到指针变量的内存里,而不是你malloc出来的缓冲区,这会直接导致内存错误!
  • sizeof taille取的是taille变量本身的大小(比如long long类型是8字节),而不是你传入的缓冲区大小的值,等于你不管分配多大的缓冲区,每次最多只读8字节,完全浪费了缓冲区空间!

二、关于你的EDIT1:修正后计时合理的原因

你说修正后得到了符合预期的计时结果,推测你应该做了这几个关键修复:

  • 把文件的open和close移到了循环内部,每次拷贝前重新打开源文件(让读指针回到文件开头),并重新创建目标文件
  • 修正了copy函数里的缓冲区传递和读取大小问题:改成传递buffer而非&buffer,用taille的值作为read的第三个参数
  • 统一了文件名的拼写(终于让删除的文件和创建的文件对应上了)

这些修改直接解决了计时异常的核心问题,现在的结果完全符合预期:缓冲区越大,拷贝耗时越低,直到达到系统IO的最优阈值(一般是4KB或8KB左右,之后耗时下降会明显变缓)。

三、针对你的EDIT2:新版copy函数是否可行?

这个版本比初始版本正确太多,但还有一个关键漏洞:write可能不会一次性写入所有数据。

根据POSIX标准,write()的返回值是实际写入的字节数,当内核缓冲区满的时候,它的返回值会小于你要求写入的t,如果不处理这种情况,会导致部分数据丢失。

所以需要给write加一个循环,确保所有数据都被写入:

void copy(int in, int out, char *buffer, size_t taille) {
    ssize_t t;
    while ((t = read(in, buffer, taille)) > 0) {
        char *ptr = buffer;
        ssize_t written;
        // 循环写入,直到所有t字节都被写完
        while (t > 0) {
            written = write(out, ptr, t);
            if (written < 0) {
                perror("error writing");
                return; // 也可以根据需求选择退出程序等错误处理方式
            }
            t -= written;
            ptr += written;
        }
    }
    if (t < 0) {
        perror("read");
    }
}

最后再给你两个小建议:

  1. 打开目标文件时,建议加上权限参数和O_TRUNC,比如open("grosfichier_copy", O_WRONLY|O_CREAT|O_TRUNC, 0644)——O_TRUNC确保每次打开时清空文件,避免旧内容残留,0644则明确设置文件权限,避免依赖系统默认的umask导致权限异常。
  2. clock()测量的是CPU时间,如果你想得到更贴近实际感知的“真实耗时”(包括IO等待时间),可以用clock_gettime(CLOCK_MONOTONIC)或者gettimeofday(),结果会更准确。

内容的提问来源于stack exchange,提问作者Jonath P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:17:47