Thus Spake Rama

A small attempt at blogging!! I will mostly be writing down funny incidents in my life and travels.

Sunday, November 22, 2009

Code aborting due to unhandled instruction error

The standard string class defined in string.h must not be used inside printf family of functions (eg fprintf, sprintf). If you do, the compiler will warn you as shown below. At runtime, the call aborts with a possible error message being "Program received signal SIGILL, Illegal instruction". Unless you look at the warnings, you wont know why the error is coming. This post is meant to help you save some trouble in such cases.

Code snippet from strings.C

Line 100: string str = "my string";
Line 101: fprintf (stderr, "%s :: No category implemented for this keyword\n", str);

$>g++ strings.C
strings.C:101: warning: cannot pass objects of non-POD type ‘const struct std::basic_string, std::allocator >’ through ‘...’; call will abort at runtime
strings.C:101: warning: format ‘%s’ expects type ‘char*’, but argument 3 has type ‘int’

Sure enough, When you run a.out, the execution aborts, but with an obscure error msg as shown below.

$>./a.out
Illegal instruction

If you run valgrind, you will get error message that would look like:

vex x86->IR: unhandled instruction bytes: 0xF 0xB 0x55 0x89
valgrind: Unrecognised instruction at address 0x405aea9.

Process terminating with default action of signal 4 (SIGILL)
Illegal opcode at address 0x405AEA9

Solution: The solution is to replace "str" as third argument of fprintf with str.c_str()!!
Compiling and running the code will give print the following o/p
my string :: No category implemented for this keyword.

Note that the compilation warning will not exist anymore.

Moral: If code aborts due to obscure error msg, look at your compiler warnings!

As usaul, any questions/clarifications, post them in comments section and I will answer them.

--rags

Labels: , , , ,

C++ and Lex/Yacc

This is some notes on lex and yacc. I think I have decent bit of knowledge in debugging linux, C/C++, lex/yacc and some related stuff, which I have accumulated over the years. I find myself telling people same stuff over and over. So this is an attempt to decrease amount of talking I do and yet share stuff with people.

For last three to four days, I have been playing with bison, bison++ and lex. The problem is like this.

I have two files, categories.lex, categories.yy. The categories.y file has some C++ code in it and my yyparse() will be called from C++ code in file test.C. If everything was in 'C' language, compilation would be straight forward. The problem is how do I compile each of these files, how do I call g++/gcc on the files so I can make a usable executable called "test". I have two bison's installed on my system. One is called "bison" which generates parser in 'C', another is called bison++ which generates parser in C++. See below for differences between bison and bison++

The solution is to export yyparse, yylex, yywrap, yyerror functions from *yy file using the phrase 'extern "C"'. Then .lex file which will be compiled with lex/gcc will get the function names in a unmangled manner.

So here are the commands I used and various error msgs I got during the process. just FYI, I have used all combinations of bison, bison++ and also tried to compile lex o/p with g++ as well as gcc. In the end, gcc for lex o/p succeeded.

$>lex -Pcategories categories.lex

This generated lex.categories.c file. Note that now yylex will be renamed to categorieslex because of the directive "-Pcategories"

$>gcc -c lex.categories.o
(note: Its GCC not G++)

$>bison -d -pcategories categories.yy

This generates file categories.tab.hh and categories.tab.cc. You must include categories.tab.hh in categories.lex. The main parse routine will now be categoriesparse() instead of yyprase (because of '-pcategories' directive).

$>g++ -c categories.tab.cc

Finally in test.C, add the following line
int categoriesparse();

You can all categoriesparse() from test.C just like anyother function.

$>g++ categories.tab.cc lex.categories.o test.o -o test

This should give you final output.

Using bison++ instead of bison in the command "bison -d -pcategories categories.yy" will generate two files categories.yy.tab.h and categories.yy.tab.c. A class of (default) name parse is created and yyparse is a member of this class. I donot really know how to use it with categories.lex file. Note that bison create a C++ file but doesnt create a class (typically named parse), where parsing routines are included. It generates non object oriented code. However, bison++ uses OOPS and creates a wrapper class for parsing.

Here are some errors I got and possible solutions to look for. Also, find my categories.lex and categories.y files attached(final working versions)

$>g++ -g -L/home/romit/java/contentanalyzer lex.categories.cc categories.tab.o test.C
lex.categories.o: In function `categorieslex':
lex.categories.c:(.text+0x227): undefined reference to `categorieslval'
categories.tab.o: In function `parse::parse()':
categories.tab.c:(.text+0x12): undefined reference to `vtable for parse'
categories.tab.o: In function `parse::parse()':
categories.tab.c:(.text+0x20): undefined reference to `vtable for parse'

Solution: You are using bison++ for categories.y. You may want to change it to bison. Also, you generated C++ code fromm categories.lex file. Generate 'C' code and use gcc to generate lex.categories.o file.

$>g++ -g -L/home/romit/java/contentanalyzer lex.categories.cc categories.tab.o test.C
categories.lex: In member function ‘virtual int categoriesFlexLexer::yylex()’:
categories.lex:11: error: ‘categorieslval’ was not declared in this scope
categories.lex:13: error: ‘STRING’ was not declared in this scope
categories.lex:17: error: ‘SEMICOLON’ was not declared in this scope
categories.lex:21: error: ‘COLON’ was not declared in this scope

You are using bison++ for categories.y and g++ for lex.categories.c
Instead use bison and gcc respectively. Explore generating lex code in 'c' instead of C++.

If you have any comments/clarifications, please post post them in comments sections and I will be happy to respond.

--Rags

Labels: , ,