C函数(fgets、scanf、fread、fwrite、fopen)的未知行为



我目前正处于计算机工程高级项目的最终开发和测试阶段。在使用libs(Libjpeg、Libbmp、PocketSphinx、Libavcodec、Libavformat、Libavutil)并使用netbeans作为IDE进行代码(C、Bash)的设计和开发之后。我遇到的问题是,在Netbeans中,代码编译和链接都很完美,软件的执行也很好。然而,当我使用MakeFile从外部编译和链接代码时,fopenfreadfwritefgetsfscanf等函数将停止工作。。。

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

编译时错误:无运行时错误:无

我第一次注意到这个问题是在代码的这一部分。

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, '', 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配置.txtOuput:正在读取配置文件。

[*]致命错误:读取配置文件时出错。

正如我所说,代码是为我的高年级项目编写的,我不能在这里发布。我确信这个问题与链接器标志有关。程序在第一次迭代时停止。正如我之前所说的,代码在使用Netbeans编译时可以工作,但在使用发布的MakeFile编译时停止工作。

---------------更新---------------

根据Jonathan Leffler的要求,以下是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;
}

您的链接标志(问题中的"ld标志")顺序错误。

程序参数到链接器(ld,通常通过gcc调用)的顺序非常重要。您应该先放源文件(对于gcc),然后放对象文件(按照依赖关系的顺序),再放库(从高级库到低级系统库)。例如,您的-lpthread应该位于-lavformat 之后

但是你真的应该学会写Makefile-s。我不知道你是否有足够的时间。好的做法是在项目开始时启动Makefile,并对其进行改进(随着代码的改进)。

您的代码在这两种情况下都能很好地编译(包括满足链接器)。

然后在这两种情况下都运行它,在后者中,当使用make构建它时,会得到意外的结果。

对我来说,这看起来更像是没有检查运行应用程序的环境。fgets的文档明确指出,NULL不仅在出现错误时返回,而且在遇到EOF时没有读取字节时也会返回。

如果您真的想知道打开了哪个文件,请使用strace,并确保在预期的环境中运行应用程序,并在适当的位置放置适当的配置文件。我相信这会让你发现问题所在。

相关内容

  • 没有找到相关文章

最新更新