32 Compiler gcc and g ++ for programming in the C language: running code

Lecture



  32 Compiler gcc and g ++ for programming in the C language: running code The g ++ compiler is distributed under the GNU license, the Free Software Foundation (FSF), for nix-like operating systems and is a C ++ compiler that is managed using the command line. g ++ is distributed with nix systems, so if you are running Unix or Linux, most likely g ++ is already installed on your system.
To run the source code using the g ++ compiler, simply type the following com in the terminal (command line) ***:

g ++ filename

After the source file is compiled into an executable file, we will get a file with the name a and the extension .out - a.out .
Before running g ++, you can specify the name of the executable file on the command line, which we get at the output. To do this, specify the -o parameter and assign the desired file name.

-o outputfile

Completely com *** and will look like this:

g ++ filename -o outputfile

In order for g ++ to show error warnings and also support existing C ++ standards, I recommend using the flags:

-Wall -ansi

If you want the compiler to treat warnings as errors, use the -Werror flag. And if at least one warning appears, you will not even get the executable file. This way you will know for sure that you have not missed a single error.

If you want to debug the executable file in the GDB debugger, include the -g flag in the *** command.

g ++ filename -g -o outputfile

This will allow the GDB debugger to give you detailed information about the debugging process, including additional code in the executable file.

If you are using * nix-like systems, you can also check other g ++ compiler options by typing the following com *** u in the command line:

man g ++

or

g ++ —help

Creating shared libraries

If you want to learn how to create a shared library on Linux with gcc, read the article How to create a shared library on Linux using gcc.

  32 Compiler gcc and g ++ for programming in the C language: running code

The gcc compiler is distributed under the GNU license, the Free Software Foundation, for nix-like operating systems, and is a C \ C ++ compiler that is managed using the command line. gcc is distributed with nix systems, so if you are running Unix or Linux, most likely gcc is already installed on your system.
To run the source code using the gcc compiler, just type the following com in the terminal (command line) *** y:

gcc filename

After the source file is compiled into the executable, we will get a file with the name a and the extension *.out - a.out , which can be run using the command

./a.out

Before running gcc, you can specify the name of the executable file on the command line, which we will get on output. To do this, set the -o parameter and assign the desired file name.

-o outputfile

Completely com *** and will look like this:

gcc filename -o outputfile

Again, you can start the program with the command ./outputfile . (The dot and slash ./ in front of the file name are used to indicate the current directory.)

To display all warnings, you must use the flag:

-Wall

To be sure that the compiler really supports ANSI standards, use the flag:

-ansi

You can read more about the meaning of compiler warnings.

If you want the compiler to treat warnings as errors, use the -Werror flag. In this case, if at least one warning occurs, you will not receive an executable file.

If you want to debug the executable file in the GDB debugger, include the -g flag in the *** command.

gcc filename -g -o outputfile

This will allow the GDB debugger to give you detailed information about the debugging process, including additional code in the executable file.

Math Library

If you need to use functions from the math library (as a rule, functions from the math.h header file, such as sin or sqrt ), you must explicitly specify this file. To bind the library, the -l flag is used, followed by the m library flag:

gcc filename -o outputfile -lm

Note that in C ++ you do not need to use this flag.
If you are using * nix-like systems, you can also check other gcc compiler options by typing the following com *** u in the command line:

man gcc

manual (in English) to the gcc compiler, or

gcc —help

manual (in Russian) to the gcc compiler.

Creating shared libraries

If you want to learn how to create a shared library on Linux with gcc, read the article: How to create a shared library on Linux using gcc.

Fix compilation errors - compile process

This is your first C (or C ++) program — it’s not that big, and you’re going to compile it. You click on the compile (or enter a com *** at the compilation) and wait. Your compiler produces fifty lines of text. You choose the words warning and error . You wonder if this means that everything is in order. You are looking for the resulting executable file. Nothing. Damn it, you think, I have to figure out what it all means ...

Types of compilation errors

First, let's distinguish between types of errors. Most compilers will display three types of warnings at compile time:

  • compiler warnings;
  • compiler errors;
  • linker errors.

  32 Compiler gcc and g ++ for programming in the C language: running code Although you don’t want to ignore them, the compiler warnings are not serious enough to not compile your program. Read the following article, which will tell you why you should be friends with the compiler and its warnings. As a rule, compiler warnings are a sign that something can go wrong during execution. How does the compiler know about it? You must have made typical mistakes that the compiler knows about. A typical example is the use of the assignment operator = instead of the equality operator == inside an expression. Your compiler may also warn you about using variables that have not been initialized and other similar errors. As a rule, you can set the level of warnings of your compiler - I set it to the highest level, so the compiler warnings do not turn into errors in the program being executed (“run errors”).

However, compiler warnings should not stop your program (unless you tell the compiler to treat warnings as errors), so they are probably not as serious as errors.

Errors are conditions that prevent the completion of the compilation of your files.

Compiler errors are limited to individual source code files and are the result of “syntax errors”. Actually, it means that you did something that the compiler cannot understand. For example, the expression for(;) syntactically incorrect, because the loop must always have three parts. Although the compiler was expecting a semicolon, it could also expect a conditional expression, so the error message you get may be something like:

line 13, unexpected parenthesis ')'

Note that compiler errors will always include the line number on which the error was found.

Even if you have completed the compilation process successfully, you may encounter linker errors. Linker errors, unlike compiler errors, have nothing to do with the wrong syntax. Instead, linker errors are usually problems finding the definition of functions, structures, classes, or global variables that were declared, but not defined, in the source code file. As a rule, these errors will look like:

could not find definition for X

Typically, the compilation process begins with a series of compilation errors and warnings and, correcting them, you will encounter linker errors. In turn, I would first fix compilation errors, and then linker errors.

Compiler errors - where to start?

If you are faced with a list of fifty or sixty errors and warnings, it will be difficult to determine where to start. The best place, however, is at the top of the list. In fact, you almost never start correcting errors from the end of the file to its beginning for one simple reason: you don’t know if they really are errors!

One error at the top of your program can cause a number of other compiler errors, because these lines can count on something at the beginning of the program that the compiler could not understand. For example, if you declare a variable with an incorrect syntax, the compiler will report syntax errors and that it cannot find the declaration for the variable. Semicolons, put in the wrong place, can lead to a huge number of errors. This happens because the C and C ++ syntax allows you to declare a type immediately after its definition:

1
2
3
4
5
struct
{
    int x;
    int y;
} myStruct;

the code will create a variable, MyStruct , with space to hold the structure containing two integers. Unfortunately, this means that if you omit the semicolon, the compiler will interpret it as if the next thing in the program is a structure (or returns a structure).

Something like that:

1
2
3
4
5
6
7
8
struct MyStructType
{
    int x;
    int y;
}
 
int foo()
{}

can lead to a huge number of errors, possibly including messages:

extraneous 'int' ignored

All this because of one character! Best to start from the top.

Error Message Analysis

Most messages from the compiler will consist of at least four things:

  1. message type - warning or error;
  2. the source file in which the error appeared;
  3. error string;
  4. A brief description of what is not working properly.

The output of g ++ for the above program may look like this (your results may differ if you use another compiler):

foo.cc:7: error: semicolon missing after struct declaration

foo.cc is the file name. 7 - line number, and it is clear that this is a mistake. The short message here is very useful, because it shows exactly what is wrong. Note, however, that the message makes sense only in the context of the program. It does not indicate which structure is missing a comma.

More confusing is another error message from the same compilation attempt:

extraneous 'int' ignored

The programmer must figure out why this happened. Note again that this error was caused by a problem at the beginning of the program, not on line 8, but earlier, when the structure lacks a semicolon. Fortunately, it is clear that the definition of the function for foo was fine, it tells us that the error should be somewhere else in the program. In fact, it should be in the program before - you will not receive an error message that indicates a syntax error before the line on which the error actually occurred.

This is the guiding principle for calculating compiler errors: if in doubt, look in the program earlier. Since syntax errors can later have serious consequences, it is possible that the compiler indicated the line number in which there was actually no syntax error!

It will be much worse if the compiler does not tell you what happened earlier in the program. Even the first compiler error you get may be related to several lines before the specified warning.

Processing incomprehensible or strange messages

There are several particularly complex types of compiler errors. The first is an undeclared variable that you think you declared. Often, you can specify exactly where the variable was declared! The problem is that often the variable is simply written with an error. Unfortunately, it is rather difficult to see, since we usually read what we expect, and not what we really are. In addition, there are other reasons why this may be a problem - for example, problems with visibility!

To sort out possible problems, I do this: in the line where the allegedly undeclared variable is located, you need to perform a search using the text editor for the word under the cursor (alternatively, you can copy the variable name and perform the search), and if I recorded it incorrectly, it will not be found . Also, do not enter the variable name manually, as you may accidentally enter it correctly.

The second incomprehensible message:

unexpected end of file

What's happening? Why is the end of the file "unexpected"? Well, the main thing here is to think like a compiler; if the end of the file is unexpected, then it must be waiting for something. What could it be? The answer is usually "completion". For example, closing curly brackets or closing quotes. A good text editor that performs syntax highlighting and automatic indentation should help correct some of these errors, making it easier to detect problems when writing code.

Ultimately, if the message is incomprehensible, then approach the problem, thinking about how the compiler is trying to interpret the file. It can be difficult when you are just starting out, but if you pay attention to the messages and try to understand what they might mean, you will quickly get used to the general patterns.

Finally, if nothing works, you can always just rewrite a few lines of code to remove any hidden syntax errors that you might not see. This can be dangerous, since you can rewrite the wrong section, but it can help.

Linker errors

After you have finally fixed all the syntax errors, took a nap, a snack a couple of times and prepared yourself mentally for the correct compilation of the program, you can still encounter linker errors. They are often quite difficult to fix, because they are not necessarily the result of what is written in your program. I will briefly describe the typical types of linker errors that can be expected, and some ways to solve them.

You may have problems with how you set up your compiler. For example, even if you include the right header files for all of your functions, you still need to provide your linker with the correct path to the library that has the actual implementation. Otherwise, you will receive an error message:

undefined function

Pay attention to the support of these functions by the compiler (this can happen if you include your own function declaration to bypass the error during compilation). If your compiler supports this feature, then problem resolution usually requires specific compiler settings. You should tell the compiler where to look for the libraries and make sure the libraries have been installed correctly.

Linker errors can occur in functions that you declared and defined if you did not include all the necessary object files in the binding process. For example, if you write a class definition in myClass.cpp , and your main function is in myMain.cpp , the compiler will create two object files, myClass.o and myMain.o, and the linker will need both of them to complete the creation of the new program. If you leave myClass.o , then it will not have a class definition, even if you correctly include myClass.h !

Sometimes minor errors occur when the linker reports more than one definition for a class, function, or variable. This problem may appear for several reasons: first, an object may have two definitions — for example, two global variables are declared as external variables, to be accessible outside the source code file. This applies to both functions and variables, and this, in fact, often happens. On the other hand, sometimes this is a problem with linker directives; Several times I have seen people include multiple copies of the same object file in the binding process. And bingo, you have several definitions. A typical manifestation of this problem is that a number of functions have several definitions.

Last weird type of linker error - message

undefined reference to main

This linker error differs from others in that it may have nothing to do with the object, including files or the correct paths to your library. On the contrary, this means that the linker tried to create an executable file and could not understand where the main() function is located. This can happen if you forget to include the main function, or if you try to compile code that has never been a separate executable file (for example, if you tried to compile a library).


Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

LINUX operating system

Terms: LINUX operating system