Search:
|
Access:
» C/C++ Programming Tools under LinuxRelated categories: C/C++ | Linux | Linux | Programming in generall Maciej ZawadzińskiViewed: 8202 | Article date: 2006-07-18 14:44:23 Within this article Maciej'll attempt to familiarise the Readers with basic techniques and tools assisting the programmer in course of developing both less and more complex software.
Within this article I will attempt to familiarise the Readers with basic techniques and tools assisting the programmer in course of developing both less and more complex software.
About the AuthorMaciej Zawadziński is a student at the Faculty of Mathematics and Computer Science of University of Wrocław, a programmer, an administrator and a fanatic of *BSD system. Member of Akademia Alternatywnych Systemów Operacyjnych (Academy of Alternate Operating Systems; http://www.aaso.pl) and a co-founder of the student association AASOC (http://www.aasoc.pwr.wroc.pl). He develops software based on Open Source technologies and takes active part in events in the IT sector. Contact: mzawadzinski@gmail.com A well-written program ought to, when an error has occurred, provide the programmer with information so detailed that he can quickly locate and fix the problem. Unfortunately most applications diverge very highly from this idealised assumption. What is more, sometimes it is very hard to determine where, and first of all - why, the problem occurs, just by looking at the source code and watching the behaviour of the program. To begin with, we can get some help here by using the tools: strace and ltrace, which do not require us to tamper with the application in any way - just run it (this is particularly useful when we don't have the source code but want to see what could have caused the error, or when we're curious about how our favourite program works...). Tracing Library Function and System Calls.The purpose of the tools: strace and ltrace is to trace executed process. The former displays system calls, the latter - calls to library functions. Furthermore, using them makes it possible to obtain information about signals the process received, arguments system calls (or library functions, respectively) were executed with and - the most important part - what their return codes were and what they mean. For starters, we shall examine a simple server of the daytime service (RFC 867), listening on TCP port 13. After the client has established a connection, the server transmits current date and time in plain text and closes it. Our program will make use of the system command date. The first version of the server can be found in listing 1. Having compiled and started the program we can see the service available on TCP port 13 (it is the port assigned to the daytime service as specified on the list of ports maintained by the organisation IANA - more information at: http://www.iana.org/). Let us try connecting to the service: # telnet 127.0.0.1 daytime Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. accept(): Bad file descriptor Connection closed by foreign host. That sure didn't look like current date! What is more, the program has returned something it shouldn't have. However, before we start poking around the source code in an attempt to locate the bug we will make use of strace. Execute the following command: # strace -p 6277 -f Then use another console to reconnect to the service, obtaining the same error message. The option -f indicates we want to trace system calls of child processes of the program under investigation, whereas -p [pid] allows us to specify the identifier of the already-running process we want to attach to. The inset ”The Command lsof” shows how one can quickly obtain the process identifier (PID) of a service knowing the port it listens on. Listing 2 shows the output of strace. We are mainly interested in child processes, i.e. those which handle connecting clients. Note the fragment highlighted in red - this is the part responsible for the error. Listing 1.Daytime.c
/* prosty serwer usługi daytime (RFC 867) */ The most important thing from our point of view is what happens to the child process which handled our client connection. Let us examine the results - the program didn't execute date, the call to execve() returned an error and the process carried on running until it has reached the call to accept(). Descriptor number 3 was not a listening socket, thus causing accept() to return the aforementioned error to stderr (in this case, the TCP connection to the client) and terminate the process. Having corrected our call to execl() and added code for handling a failure we have managed to get our program to start running properly. As it turns out we have passed an incorrect argument to execl(), furthermore we did not anticipate that call returning an error, thus leaving the child process active and executing the code of its parent. The most simple solution here is to put exit(0) after calling execl(). The corrected code could look like this: ... execl("/bin/date","date",0); exit(1); } This time the source code of the program was very short, so we could have pinpointed the potential source of problems immediately. Then again, while working on larger projects it might turn out too tedious or even virtually impossible to succeed in reasonable time to be searching for such bugs in the source code. Note that even though our corrected program works, it contains another, serious yet commonly ignored bug. We'll get to that in a moment. Listing 2. The output of strace
root@3[artykul]# strace -p 6277 -f
|
|
Copyright C 2006 by Software Developer's Journal. All rights reserved.






SDJ Users:
Shopping Cart









