Неизвестное поведение с функциями C (fgets, scanf, fread, fwrite, fopen) - PullRequest
0 голосов
/ 14 февраля 2012

В настоящее время я нахожусь в стадии окончательной разработки и тестирования моего старшего проекта по компьютерной инженерии.После выполнения проектирования и разработки кода (C, Bash) с библиотеками (Libjpeg, Libbmp, PocketSphinx, Libavcodec, Libavformat, Libavutil) и использованием сетевых компонентов в качестве IDE.У меня проблема в том, что в Netbeans код отлично компилируется и связывается, и выполнение программного обеспечения тоже хорошо.Однако, когда я компилирую и связываю код извне, используя MakeFile, такие функции, как: fopen, fread, fwrite, fgets, fscanf и т. Д., Перестают работать ...

GCC-FLAGS:

-m32 -O3 -W -Wall -std=gnu99 -pedantic -Wbad-function-cast -Wcast-align -Wcast-qual \
-Wchar-subscripts -Winline -Wmissing-prototypes -Wnested-externs -Wpointer-arith \
-Wredundant-decls -Wshadow -Wstrict-prototypes -Wwrite-strings -Wformat-nonliteral \
-Wformat-security -ftrapv -lrt -Wno-unused \
-DMODELDIR=\"`pkg-config --variable=modeldir pocketsphinx`\" \
`pkg-config --cflags --libs pocketsphinx sphinxbase` \
`pkg-config --cflags --libs sndfile`

LD-FLAGS:

-I/usr/local/lib -I/usr/local/include -I/usr/local/lib/pkgconfig -lpthread \
-lpocketsphinx -lsndfile -ljpeg -lavformat -lavcodec -ldl -lasound -lz -lswscale \
-lavutil -lm

То же неизвестное поведение также влияет на производительность PocketSphinx, котораятеперь не могу открыть HMM.

Любое просветление действительно ценится, так как моя последняя презентация на следующей неделе.

---------- ОБНОВЛЕНИЕ ----------

Это мой фактический MakeFile

.SUFFIXES: .o .c
.c.o: $(CC) -c $(CFLAGS) $<

# Compiler and Flags 
CC = gcc
CFLAGS = -m32 -O3 -W -Wall -std=gnu99 -pedantic -Wbad-function-cast -Wcast-align -Wcast-qual -Wchar-subscripts -Winline -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-prototypes -Wwrite-strings -Wformat-nonliteral -Wformat-security -ftrapv -Wno-unused -DMODELDIR=\"`pkg-config --variable=modeldir pocketsphinx`\"`pkg-config --cflags --libs pocketsphinx sphinxbase` `pkg-config --cflags --libs sndfile`

# Libraries
LIBS = -I/usr/local/lib -I/usr/local/include -I/usr/local/lib/pkgconfig -lpocketsphinx -lsndfile -ljpeg -lavformat -lavcodec -ldl -lasound -lz -lswscale -lavutil -lm

# Source files
SRC= libbmp.c state.c secure.c audio.c config.c engine.c helpers.c macmp2.c queue.c image.c video.c

# Object Files
OBJ= libbmp.o state.o secure.o audio.o config.o engine.o helpers.o macmp2.o queue.o image.o video.o

# Executable file
EXECUTABLE = macmp2

# Explicit rule
hist: $(OBJ)
    $(CC) $(CFLAGS) -o $(EXECUTABLE) $(OBJ) $(LIBS)

clean:
    rm -f *.o
    rm -f $(EXECUTABLE)

# Implicit rules
audio.o: macmp2.h libbmp.h audio.c
config.o: macmp2.h libbmp.h config.c
engine.o: macmp2.h libbmp.h engine.c
helpers.o: macmp2.h libbmp.h helpers.c
image.o: macmp2.h libbmp.h image.c
libbmp.o: libbmp.h libbmp.c
macmp2.o: macmp2.h libbmp.h macmp2.c
queue.o: macmp2.h libbmp.h queue.c
secure.o: macmp2.h libbmp.h secure.c
state.o: macmp2.h libbmp.h state.c
video.o: macmp2.h libbmp.h video.c

Ошибки времени компиляции: нет Run-TimeОшибки: нет

Я впервые заметил проблему в этой части кода.

void load_configuration (macmp2_state * s)
{
    register uint32_t it = 0x0;                     /* Iterator */
    register uint32_t size = get_file_size (s);     /* Configuration File Size */
    char * new_entry = (char *) malloc_safe (sizeof (char) * LINE_LENGTH * 5, s);
    char * error_msg = (char *) malloc_safe (sizeof (char) * LINE_LENGTH * 5, s);
    char * filename = NULL;                         /* Filename Token */
    char * pmode = NULL;                            /* Processing Mode Token */
    char * token = NULL;                            /* String Token */
    FILE * fp = NULL;                               /* File Pointer */

    /* Temporary Variables */
    video_file * v = (video_file *) malloc_safe (sizeof(*v), s);
    image_file * i = (image_file *) malloc_safe (sizeof(*i), s);
    audio_file * a = (audio_file *) malloc_safe (sizeof(*a), s);

#ifdef DEBUG
    fprintf (stderr, "Reading configuration file.\n");
#endif

    fp = fopen_safe (s->config_file, "r", s);

    for (it = size; it > 0x0; it--)
    {
        /* Initializing Variables */
        memset (new_entry, '\0', LINE_LENGTH * 5);
        init_video_file (v);
        init_image_file (i);
        init_audio_file (a);

        /* Extracting entry from configuration file */        
        if (fgets (new_entry, (LINE_LENGTH * 5 * sizeof(char)), fp) == NULL)
        {
            fatal_error (s, "Error reading configuration file.");
        }

При компиляции с MakeFile я всегда получаю «Файл конфигурации чтения ошибок», однако я не получаю его на Netbeans.

Ввод программы: ./macmp2-c configuration.txt Выход: чтение файла конфигурации.

[*] Неустранимая ошибка: ошибка чтения файла конфигурации.

Как я уже сказал, код для моего старшего проекта, я не могуразместите это здесь.Я уверен, что проблема связана с флагами линкера.Программа останавливается на первой итерации.Как я уже говорил, код работает при компиляции с Netbeans, но перестает работать при компиляции с использованием опубликованного файла MakeFile.

---------- ОБНОВЛЕНИЕ ---------

По просьбе Джонатана Леффлера, вот обертки для fopen_safe и malloc_safe.

Код для fopen_safe и malloc_safe, которые оба реализованы мной.

void * malloc_safe (size_t size, macmp2_state * s)
{
    void * ptr = malloc (size);

    if (ptr == NULL)
    {
        fatal_error (s, "Memory could not be allocated.");
    }
    return ptr;
}

FILE * fopen_safe (const char * filename, const char * mode, macmp2_state * s)
{
    FILE * stream = fopen (filename, mode);

    if (stream == NULL)
    {
        fatal_error (s, "Stream could not be open.");
    }
    return stream;
}

Ответы [ 2 ]

2 голосов
/ 14 февраля 2012

Флаги вашей ссылки ("ld-flags" в вашем вопросе) расположены в неправильном порядке.

Порядок аргументов программы для компоновщика (ld, часто вызывается через gcc) имеет большое значение. Сначала вы должны поместить свои исходные файлы (для gcc), затем ваши объектные файлы (в порядке зависимостей), а затем библиотеки (от высокоуровневых до низкоуровневых системных). Например, ваш -lpthread должен быть расположен после -lavformat

Но вы действительно должны научиться писать Makefile -s. Я не знаю, достаточно ли у вас времени. Хорошей практикой является запуск вашего Makefile в начале проекта и его улучшение (по мере улучшения вашего кода).

0 голосов
/ 21 февраля 2012

Ваш код прекрасно компилируется в обеих ситуациях (включая удовлетворение компоновщика).

Затем вы запускаете его в обеих ситуациях, и в последнем случае, собрав его с помощью make, вы получите неожиданный результат.

Для меня это больше похоже на то, что вы не проверяете среду, в которой запускаете свое приложение. В документации по fgets четко указано, что NULL возвращается не только в случае ошибки, но и в том случае, если при обнаружении EOF не было прочитано ни одного байта.

Если вы действительно хотите знать, какой файл открыт, используйте strace и убедитесь, что вы запускаете приложение в ожидаемой среде с правильным файлом конфигурации на своем месте. Я уверен, что это позволит вам найти проблему.

...