文件指针行为?

时间:2009-02-28 00:39:37

标签: c++ c file

这是参考我之前提出的问题 -

What is the correct way to declare and use a FILE * pointer in C/C++?

MyFile.h
char         sMsg[712]      = "";

#define STD_MSG(string) \
fprintf (stderr, string)

#define ERR_MSG(fp, string) \
fprintf (fp, "%s\n", string);\
fflush (fp)

MyFile.C
#include "PdmTestClnt.h"

//---------------------------------------------------------------
// ** Global variables
//---------------------------------------------------------------
FILE * fpErr = NULL;

funcxyz() {
//FILE * fpErr1 = NULL; 
sprintf (sMsg, "************ CHECKING FOR THE CRASH ************. \n");
ERR_MSG (fpErr, sMsg);
//ERR_MSG (fpErr1, sMsg);
}

//========================================================================
// Main
//========================================================================
integer main (integer argc, char ** argv)
{
   //FILE * fpErr = NULL;

   if (!(fpErr = sysFopen (sErrFileName, "a+")))
   {
      sprintf (sMsg,"Error in opening file %s", sErrFileName);
      STD_MSG (sMsg);
   }

     // Log in the error file
     sprintf (sMsg, "Log into the error file. \n");
     ERR_MSG (fpErr, sMsg);

funcxyz();

}

如果File指针被声明为global,则它可以工作。但如果它被声明为local,则会导致内存错误(coredump)。

继续:

HP Unix Itanium

aCC编译器(C ++编译器)

有人可以解释这种行为吗?

编辑:抱歉没有编辑问题。我现在理解printf()/ fprintf()的问题。在我的回答中,我在Windows上使用Dev C ++编译器显示了printf()/ fprintf()的结果。但是当我使用aCC编译器在HP Unix上运行它时,它会完全忽略%s并始终正确打印字符串。那么如何让我的架构师在没有向他展示Unix内存故障的情况下更改它呢?

感谢。

3 个答案:

答案 0 :(得分:5)

假设在本地你的意思是funcxyz()取消注释fpErr1,它会因为你没有打开文件而发生段错误。您不能在那里使用NULL,您希望数据在哪里?

我建议编写funcxyzfpErr1作为参数,例如:

funcxyz(FILE *fpErr1) {
   //FILE * fpErr1 = NULL; 
   sprintf (sMsg, "************ CHECKING FOR THE CRASH ************. \n");
   ERR_MSG (fpErr1, sMsg);
   //ERR_MSG (fpErr1, sMsg);
}

然后从主要调用它:

 ...
 funcxyz(fpErr);
 ...

答案 1 :(得分:2)

此信息对此问题无关紧要。在回答之前,我应该仔细阅读。 = X

您的问题是,您正在使用本地范围中的fpErr隐藏全局范围。例如:

int var = 0;

void print_var() {
    printf("print_var: %d\n", var);
}

int main() {
    int var = 42;

    printf("main: %d\n", var);
    print_var();

    return 0;
}

如果运行代码,输出应为:

main: 42
print_var: 0

在您的情况下,fpErr的值为NULL(0),因此文件I / O函数会尝试访问NULL处的数据,这会导致分段错误。

答案 2 :(得分:2)

不要在标题中定义变量 - 这是一个讨厌的习惯。

从标题中的sMsg[]中删除初始化程序,并添加“extern” - 并使用初始化程序在适当的源文件中定义变量(如果标题为MyFile,则通常为MyFile.c) 。H)。当几个源文件使用MyFile.h时,这真的很重要 - 如果它只被一个源文件使用,为什么你首先使用头文件?

您的代码还包括'PdmTestClnt.h'而不是MyFile.h - 我们是否应该假设MyFile.h是您要包含的内容?

funcxyz()没有返回类型 - 它不会在C ++或严格的C99编译器下编译。为什么函数格式化为sMsg,然后使用fprintf()复制字符串? fprintf()可以完成整个工作(然后是一些工作)。

为什么需要全局定义

当你有一个全局变量时,main()中的代码通过调用fopen()来初始化它,其他函数可以使用初始值。那很方便。当你有一个局部变量时,你必须初始化它。这是一个痛苦,因为你最终打开文件很多次,有很多不必要的副作用 - 使用太多的文件句柄,你必须关闭它们,你可能会继续截断文件中已有的输出。为避免这种情况,请将文件指针传递给函数 - 或接受全局正常。考虑一下 - 以某种形式或形式,名称stdinstdoutstderr也指全局变量。

void funcxyz(FILE *fp)
{
    sprintf(sMsg, "************ CHECKING FOR THE CRASH ************. \n");
    ERR_MSG (fpErr, sMsg);
}

int main(int argc, char **argv)
{
    FILE *fpErr = NULL;

    if ((fpErr = sysFopen(sErrFileName, "a+")) != 0)
    {
        sprintf(sMsg,"Error in opening file %s", sErrFileName);
        STD_MSG(sMsg);
    }

    // Log in the error file
    sprintf(sMsg, "Log into the error file. \n");
    ERR_MSG(fpErr, sMsg);

    funcxyz(fpErr);
    return(0);
}