0

I'm currently in the phase of final development and testing of my computer engineering senior project. After doing the design and development of the code (C, Bash) with libs (Libjpeg, Libbmp, PocketSphinx, Libavcodec, Libavformat, Libavutil) and using netbeans as IDE. The problem I have is that in Netbeans the code compiles and links perfectly and the execution of the software is fine too. However, when I compile and link the code externally using a MakeFile, functions like: fopen, fread, fwrite, fgets, fscanf, etc stop working...

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

The same unknown behavior is also affecting the performance of PocketSphinx which is now not able to open HMM.

Any enlightenment is really appreciated as my final presentation is next week.

---------- UPDATE ----------

This is my actual 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

Compile-Time Errors: None Run-Time Errors: None

I first notice the issue in this part of the code.

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.");
        }

I'm always getting the "Error Reading Configuration file", when compiling with the MakeFile, however I don't get it on Netbeans.

Program Input: ./macmp2 -c configuration.txt Ouput: Reading configuration file.

[*] Fatal Error: Error reading configuration file.

As I said, the code is for my senior project, I can't post it here. I'm pretty sure the issue has to do with the Linker Flags. The program stops at the first iteration. As I said before the code works when compiled with Netbeans, but stops working when compiled using the posted MakeFile.

---------- UPDATE ----------

As requested by Jonathan Leffler, here are the wrappers for fopen_safe and malloc_safe.

Code for fopen_safe and malloc_safe which are both implemented by me.

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;
}
  • 1
    One week probably isn't enough time. If building under Make was a goal of your project, you should have made it so from the beginning, not as an afterthought. – Beta Feb 14 '12 at 17:08
  • 3
    "stop working" is not something we can help you with. If you have a compile-time error, post it. If you get a run-time crash, describe it. If the output is not what you expect, detail the input. Post some code. – abelenky Feb 14 '12 at 17:09
  • Be aware that `-I` flags affect the C pre-processor, not the linker. Listing them in `LDFLAGS` might not matter too much, but does show a conceptual problem. Arguably, the two invocations of `pkg-config` including `--libs` listed in GCC flags should be in the LDFLAGS section. If both are always used, you'll be OK. But some versions of GCC complain (or, more likely, used to complain; I don't recall seeing the wittering for several years now) when you create object files and specify libraries on the command line. (The `-lrt` in GCC flags is a library reference, too!) – Jonathan Leffler Feb 14 '12 at 17:25
  • I update my post, with the source code for the MakeFile. –  Feb 14 '12 at 18:20
  • Your `LIBS` has probably a wrong order. Read also the tutorial documentation of GNU Make – Basile Starynkevitch Feb 14 '12 at 18:24
  • The code you've given us is neither necessary nor sufficient to reproduce the error (the excerpt ends in the middle of a *for loop???*). Can you verify that the two versions call this function with the same argument? Can you tell which iteration through the loop causes the error? Can you verify the results of `malloc_safe` and `fopen_safe`? – Beta Feb 14 '12 at 18:44
  • As I said, the code is for my senior project, I can't post it here. I'm pretty sure the issue has to do with the Linker Flags. The program stops at the first iteration. As I said before the code works when compiled with Netbeans, but stops working when compiled using the posted MakeFile. –  Feb 14 '12 at 18:54
  • Try to use a debugger (like `gdb`) to understand what is happenning. If you suspect a `make` issue, consider using `remake` to debug it... – Basile Starynkevitch Feb 14 '12 at 21:26
  • @JonathanLeffler The double PKG-CONFIG in the Compiler Flags is taken directly from PocketSphinx documentation. [PocketSphinx Documentation](http://cmusphinx.sourceforge.net/wiki/tutorialpocketsphinx) –  Feb 15 '12 at 07:26
  • You don't test the return value from `fopen_safe()` - does it guarantee never to return a NULL pointer if the file can't be opened? Similar comments apply to your `malloc_safe()` calls, etc. They're non-standard functions, so while we can guess they are some sort of cover for `fopen()` and `malloc()`, we can't tell what particular version of 'safety' they provide. – Jonathan Leffler Feb 15 '12 at 07:31
  • You are going to have to work out what NetBeans does that is different from what your Makefile does. Because that difference is probably going to account for your problem. They can't be identical; if they were, you'd get the same behaviour. So, what is different about the way NetBeans compiles the program? It might be an environment variable, or different options, or ... – Jonathan Leffler Feb 15 '12 at 07:34
  • @JonathanLeffler Just posted the code for fopen_safe and malloc_safe. I'm currently trying to figured out what's different between netbeans makefile and my own makefile, I'm guessing the same (environment variable, included directories). –  Feb 15 '12 at 15:31
  • Those 'safe' functions allow you not to check return values; they're guaranteed not to return null pointers. They are not directly a source of your problem, after all. The concept is not unusual; there are many systems that use `xmalloc()` and some that use `emalloc()` for `malloc_safe()`. There is also a set of functions such as `fopen_s()`, though, which are also 'safe' or 'secure'. They're defined in [TR24731](http://stackoverflow.com/questions/372980/do-you-use-the-tr-24731-safe-functions), but these can return NULL, and you might have been emulating them. These originate with Microsoft. – Jonathan Leffler Feb 15 '12 at 15:38
  • You should upgrade your DEBUG statement to print the file name that is about to be opened, and you should compile with `-DDEBUG` added to the compilation options (see also [How to define a macro for debug printing?](http://stackoverflow.com/questions/1644868)). See whether your `make`-compiled program is opening the same file that the Netbeans-compiled program is opening. – Jonathan Leffler Feb 15 '12 at 15:45

2 Answers2

2

Your link flags ("ld-flags" in your question) are in wrong order.

Order of program arguments to linker (ld, often invoked thru gcc) matters a lot. You should put your source files first (for gcc), then your object files (in order of dependencies), then the libraries (from the higher-level ones to the low-level system ones). For instance, your -lpthread should be positioned after -lavformat

But you really should learn to write Makefile-s. I don't know if you have enough time. The good practice is to start your Makefile at the beginning of the project and to improve it (as you improve your code).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

Your code compiles just fine in both situations (including the linker being satisfied).

Then you run it in both situations and in the latter, when having built it using make, you get an unexpected result.

To me, this looks more like you not checking the environment where you run your application. The documentation for fgets clearly states that NULL is returned not only on error but also if no bytes have been read when EOF is encountered.

If you really want to know which file is opened, use strace, and make sure that you run the application in the expected environment with the proper configuration file in its proper place. I'm sure this will let you find the problem.

HonkyTonk
  • 1,961
  • 11
  • 11