C-关闭文件时出现分段错误

C-关闭文件时出现分段错误,c,fclose,C,Fclose,我遇到了一个奇怪的问题,在尝试关闭文件时,我收到了一个分段错误。数据正在正确写入文件,在fflush和fclose之间是否会发生某种竞争情况 //main.c #define filename "/home/test.txt"; char fbuf[255]; sprintf(fbuf, "%s, %f, %f,%f \n", "big", 8.0,0.0,0.8); sendFile(&fbuf, sizeof(fbuf), (void *)filename); static v

我遇到了一个奇怪的问题,在尝试关闭文件时,我收到了一个分段错误。数据正在正确写入文件,在fflush和fclose之间是否会发生某种竞争情况

//main.c

#define filename "/home/test.txt";
char fbuf[255];
sprintf(fbuf, "%s, %f, %f,%f \n", "big", 8.0,0.0,0.8);

sendFile(&fbuf, sizeof(fbuf), (void *)filename);

static void
sendFile( void *data, int size, char *pName)
{
    FILE *pFile = fopen(pName,"a");
    char *buf = NULL;
    buf = (char *)malloc(255);
    memcpy(buf, data, sizeof(char *)*size);

    if(pFile == NULL) {
        logger(LOG_INFO, "Error opening file\n");
}
    else {
        fwrite(buf, 1, strlen(buf), pFile);
        fflush(pFile);
        fclose(pFile);
    }
    free (buf);
}

非常感谢您的帮助或建议。

我认为问题出在
memcpy(buf、data、sizeof(char*)*size)

它不应该是简单的
memcpy(buf、数据、大小)


看看您的示例,
fbuf
(即
data
)是255个字符,
buf
也是255个字符。但是
memcpy
正在复制超过1000个字符,有效地将垃圾写入堆中,结果不可预测。

我认为问题在于
memcpy(buf,data,sizeof(char*)*size)

它不应该是简单的
memcpy(buf、数据、大小)


看看您的示例,
fbuf
(即
data
)是255个字符,
buf
也是255个字符。但是
memcpy
正在复制超过1000个字符,有效地将垃圾写入堆中,结果是不可预测的。

下面是一个有效的代码版本,其中嵌入了一些注释,说明为什么事情与发布的代码不同

注意:在linux(和其他操作系统)上,没有管理权限,
/home
目录是不可写的。因此对
fopen()
的调用总是会失败

//main.c

#include <stdio.h>  // fwrite, fopen, fclose, perror
#include <stdlib.h> // exit, EXIT_FAILURE
#include <string.h> // strlen, sprintf, memcpy

// note: no comments at end of #define statement as the comment would be copied into the code
// note no ';' at end of #define statement
#define filename "/home/test.txt"
 // to avoid using 'magic' numbers in code
 // and this name used throughout the code
#define BUF_SIZE (255)

// prototypes
void sendFile( char *, char *); // so compiler does not make incorrect assumptions
                                // and no second parameter needed

char fbuf[BUF_SIZE] = {'\0'}; // avoid 'magic' numbers
                              // avoid placing trash into output file
                              // however, will place many NUL bytes

// main() function to make executable platform for testing
int main( void )
{
    sprintf(fbuf, "%s, %f, %f,%f \n", "big", 8.0, 0.0, 0.8);
     // changed 3rd parameter type to match actual function parameter type
    sendFile(fbuf, filename); // no '&' because in C
                              // array name degrades to address of array
    return 0;
}

void sendFile( char *data, char *pName) // use actual parameter types
{
    FILE *pFile = fopen(pName,"a");
    if(pFile == NULL)  // always check for error immediately after call to system function, not later
    { // then fopen failed
         perror( "fopen failed" );
        //logger(LOG_INFO, "Error opening file\n");
        exit( EXIT_FAILURE); // exit, so no other code executed
    }

    // implied else, fopen successful

    char *buf = NULL;
    if(NULL == (buf = malloc(BUF_SIZE) ) ) // don't cast returned value
    { // then malloc failed   -- always check for error immediately after call to system function
        perror( "malloc for output buffer failed");
        //logger(LOG_INFO, "malloc for BUF_SIZE failed");
        fclose( pFile); // cleanup
        exit(EXIT_FAILURE);  // exit, so no other code executed
    }

    // implied else, malloc successful

    memcpy(buf, data, BUF_SIZE); // using original 3rd parameter would move 4 times as many bytes,
                             // I.E. past the end of the source buffer and past the end of the destination buffer
                             // resulting in undefined behaviour, leading to a seg fault event
                             // this memcpy() and the destination buffer
                             // are unneeded as first passed in parameter
                             // contains ptr to the source buffer
                             // which can be used in the call to fwrite()

    fwrite(buf, BUF_SIZE, 1, pFile); // buf will have NUL byte immediately after 'big' so strlen() would return 3
                                     // and the syntax for fwrite is source buffer, size of one item, number of items, FILE*
                                     // and this parameter order is best
                                     // because, if error checking,
                                     // can just compare returned value to 1
    fflush(pFile);  // not actually needed as the fclose() performs a flush
    fclose(pFile);

    free (buf);     // original code did this even if malloc had failed
                    // and even if the fopen had failed
                    // which would have corrupted the 'heap' leading to a seg fault event
}
//main.c
#包括//fwrite、fopen、fclose、peror
#包括//退出,退出\失败
#包括//strlen、sprintf、memcpy
//注意:在#define语句末尾没有注释,因为注释将被复制到代码中
//注:无“;”在#define语句末尾
#定义文件名“/home/test.txt”
//避免在代码中使用“神奇”数字
//这个名字贯穿了整个代码
#定义基本单位大小(255)
//原型
void sendFile(char*,char*);//所以编译器不会做出错误的假设
//而且不需要第二个参数
char fbuf[BUF_SIZE]={'\0'};//避免使用“神奇”数字
//避免将垃圾放入输出文件中
//但是,将放置许多NUL字节
//main()函数,用于创建可执行的测试平台
内部主(空)
{
sprintf(fbuf,“%s,%f,%f,%f\n”,“大”,8.0,0.0,0.8);
//更改了第三个参数类型以匹配实际功能参数类型
sendFile(fbuf,filename);//否'&',因为在C中
//数组名称降级为数组的地址
返回0;
}
void sendFile(char*data,char*pName)//使用实际参数类型
{
文件*pFile=fopen(pName,“a”);
if(pFile==NULL)//总是在调用系统函数后立即检查错误,而不是稍后
{//然后fopen失败了
perror(“fopen失败”);
//记录器(日志信息,“打开文件时出错”);
exit(exit_FAILURE);//exit,因此不执行其他代码
}
//否则,fopen成功了
char*buf=NULL;
if(NULL==(buf=malloc(buf_SIZE))//不强制转换返回值
{//然后malloc失败--总是在调用系统函数后立即检查错误
perror(“输出缓冲区的malloc失败”);
//记录器(日志信息,“BUF_大小的malloc失败”);
fclose(pFile);//清除
exit(exit_FAILURE);//exit,因此不执行其他代码
}
//否则,malloc成功了
memcpy(buf,data,buf_SIZE);//使用原始的第3个参数将移动4倍的字节,
//即,超过源缓冲区的结尾和目标缓冲区的结尾
//导致未定义的行为,导致seg故障事件
//这个memcpy()和目标缓冲区
//不需要作为第一个传入参数
//包含到源缓冲区的ptr
//可以在调用fwrite()时使用
fwrite(buf,buf_SIZE,1,pFile);//buf将在'big'之后立即有NUL字节,因此strlen()将返回3
//fwrite的语法是源缓冲区、一个项目的大小、项目数、文件*
//这个参数顺序是最好的
//因为如果检查错误,
//只能将返回值与1进行比较
fflush(pFile);//实际上不需要,因为fclose()执行刷新
fclose(pFile);
free(buf);//即使malloc失败,原始代码也会这样做
//即使fopen失败了
//这会损坏“堆”,导致seg故障事件
}

这是一个有效的代码版本,其中嵌入了一些注释,说明为什么与发布的代码不同

注意:在linux(和其他操作系统)上,没有管理权限,
/home
目录是不可写的。因此对
fopen()
的调用总是会失败

//main.c

#include <stdio.h>  // fwrite, fopen, fclose, perror
#include <stdlib.h> // exit, EXIT_FAILURE
#include <string.h> // strlen, sprintf, memcpy

// note: no comments at end of #define statement as the comment would be copied into the code
// note no ';' at end of #define statement
#define filename "/home/test.txt"
 // to avoid using 'magic' numbers in code
 // and this name used throughout the code
#define BUF_SIZE (255)

// prototypes
void sendFile( char *, char *); // so compiler does not make incorrect assumptions
                                // and no second parameter needed

char fbuf[BUF_SIZE] = {'\0'}; // avoid 'magic' numbers
                              // avoid placing trash into output file
                              // however, will place many NUL bytes

// main() function to make executable platform for testing
int main( void )
{
    sprintf(fbuf, "%s, %f, %f,%f \n", "big", 8.0, 0.0, 0.8);
     // changed 3rd parameter type to match actual function parameter type
    sendFile(fbuf, filename); // no '&' because in C
                              // array name degrades to address of array
    return 0;
}

void sendFile( char *data, char *pName) // use actual parameter types
{
    FILE *pFile = fopen(pName,"a");
    if(pFile == NULL)  // always check for error immediately after call to system function, not later
    { // then fopen failed
         perror( "fopen failed" );
        //logger(LOG_INFO, "Error opening file\n");
        exit( EXIT_FAILURE); // exit, so no other code executed
    }

    // implied else, fopen successful

    char *buf = NULL;
    if(NULL == (buf = malloc(BUF_SIZE) ) ) // don't cast returned value
    { // then malloc failed   -- always check for error immediately after call to system function
        perror( "malloc for output buffer failed");
        //logger(LOG_INFO, "malloc for BUF_SIZE failed");
        fclose( pFile); // cleanup
        exit(EXIT_FAILURE);  // exit, so no other code executed
    }

    // implied else, malloc successful

    memcpy(buf, data, BUF_SIZE); // using original 3rd parameter would move 4 times as many bytes,
                             // I.E. past the end of the source buffer and past the end of the destination buffer
                             // resulting in undefined behaviour, leading to a seg fault event
                             // this memcpy() and the destination buffer
                             // are unneeded as first passed in parameter
                             // contains ptr to the source buffer
                             // which can be used in the call to fwrite()

    fwrite(buf, BUF_SIZE, 1, pFile); // buf will have NUL byte immediately after 'big' so strlen() would return 3
                                     // and the syntax for fwrite is source buffer, size of one item, number of items, FILE*
                                     // and this parameter order is best
                                     // because, if error checking,
                                     // can just compare returned value to 1
    fflush(pFile);  // not actually needed as the fclose() performs a flush
    fclose(pFile);

    free (buf);     // original code did this even if malloc had failed
                    // and even if the fopen had failed
                    // which would have corrupted the 'heap' leading to a seg fault event
}
//main.c
#包括//fwrite、fopen、fclose、peror
#包括//退出,退出\失败
#包括//strlen、sprintf、memcpy
//注意:在#define语句末尾没有注释,因为注释将被复制到代码中
//注:无“;”在#define语句末尾
#定义文件名“/home/test.txt”
//避免在代码中使用“神奇”数字
//这个名字贯穿了整个代码
#定义基本单位大小(255)
//原型
void sendFile(char*,char*);//所以编译器不会做出错误的假设
//而且不需要第二个参数
char fbuf[BUF_SIZE]={'\0'};//避免使用“神奇”数字
//避免将垃圾放入输出文件中
//但是,将放置许多NUL字节
//main()函数,用于创建可执行的测试平台
内部主(空)
{