Поведение указателя файла? - PullRequest
0 голосов
/ 28 февраля 2009

Это со ссылкой на вопрос, который я задавал ранее -

Как правильно объявить и использовать указатель FILE * в 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 объявлен глобальным, он работает. Но если он объявлен локальным, это приведет к ошибке памяти (coredump).

Пробежал по:

HP Unix Itanium

компилятор aCC (компилятор C ++)

Может кто-нибудь объяснить поведение?

Редактировать: Извините, что не редактировал вопрос. Теперь я понимаю проблему с printf () / fprintf (). В моем ответе я показал результаты для printf () / fprintf () с компилятором Dev C ++ для Windows. Но когда я запускаю его на HP Unix с компилятором aCC, он полностью игнорирует% s и всегда правильно печатает строку. Так как мне попросить моего архитектора изменить его, не показывая ему ошибки памяти в Unix?

Спасибо.

Ответы [ 3 ]

5 голосов
/ 28 февраля 2009

Предполагая, что под local вы подразумеваете в 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);
 ...
2 голосов
/ 28 февраля 2009

Не определяйте переменные в заголовках - это неприятная привычка.

Удалите инициализатор из sMsg[] в заголовке и добавьте 'extern' - и определите переменную с инициализатором в соответствующем исходном файле (обычно MyFile.c, если заголовок MyFile.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);
}
2 голосов
/ 28 февраля 2009

Эта информация не имеет отношения к вопросу. Я должен прочитать более внимательно, прежде чем я отвечу. = 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) и, таким образом, функции файлового ввода-вывода пытаются получить доступ к данным на NULL, что вызывает ошибку сегментации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...