这是参考我之前提出的问题 -
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内存故障的情况下更改它呢?
感谢。
答案 0 :(得分:5)
假设在本地你的意思是funcxyz()
取消注释fpErr1,它会因为你没有打开文件而发生段错误。您不能在那里使用NULL
,您希望数据在哪里?
我建议编写funcxyz
以fpErr1
作为参数,例如:
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()
来初始化它,其他函数可以使用初始值。那很方便。当你有一个局部变量时,你必须初始化它。这是一个痛苦,因为你最终打开文件很多次,有很多不必要的副作用 - 使用太多的文件句柄,你必须关闭它们,你可能会继续截断文件中已有的输出。为避免这种情况,请将文件指针传递给函数 - 或接受全局正常。考虑一下 - 以某种形式或形式,名称stdin
,stdout
和stderr
也指全局变量。
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);
}