LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Crashes in throwing exceptions if code compiled in 32 bit explicity on 64 bit system (https://www.linuxquestions.org/questions/programming-9/crashes-in-throwing-exceptions-if-code-compiled-in-32-bit-explicity-on-64-bit-system-925955/)

gaurav.rustagi 01-27-2012 05:58 AM

Crashes in throwing exceptions if code compiled in 32 bit explicity on 64 bit system
 
Hi LQ Memebers,

We have one shared libary which is used by Java Program using JNI. In this native libary, we throw standard exception using JNI methods,which by the way work fine.

Due to some constraint, we are forced to compile this library in both modes ( 32 & 64 bit) only on 64 bit server using -m32 options.

Now, the 32 bit compiled version is run on 32 bit systems and the libary crashes while attempting to throw an exception to Java program. However, if the libary is compiled on 32 bit system, it works just fine.

This is my error class,

#include <exception>
#include <sstream>

//! Base error class
class Error : public std::exception {
public:
/*! The explicit use of this constructor is not advised. Use the GO_FAIL macro instead */
Error(const std::string& message = "") : message_(message) {};

/*! the automatically generated destructor would not have the throw specifier */
virtual ~Error() throw() {}

//! returns the error message.
const char* what() const throw () { return message_.c_str(); }

private:
std::string message_;
};

Usage :
throw Error("Any error");

the program fails with the following msg.

terminate called after throwing an instance of 'Error'
what(): Any error


But if i compiled my library on 32 bit system itself, it just throws an error msg..

Any error

Why is this happening ? I have also tried taking the code in debug (gdb), but the control never reaches catch block.

Any help would be highly appreciated..

Thanks,
Gaurav

gaurav.rustagi 01-27-2012 08:47 AM

Any body.. pls put forth your comments..

dwhitney67 01-27-2012 12:01 PM

Quote:

Originally Posted by gaurav.rustagi (Post 4585896)
Any body.. pls put forth your comments..

Presumably, when a ball is thrown, there's someone else to catch it. It's the same concept when dealing with exceptions... if one is thrown, then somewhere in the code, it should be caught.

Try augmenting your code to have the following construct:
Code:

...

try
{
  throw Error("Any error");
}
catch (std::exception& e)
{
  std::cout << e.what() << std::endl;
}

...


NevemTeve 01-27-2012 02:04 PM

Are you sure that it is okay to use C++ from JNI?

gaurav.rustagi 01-27-2012 02:21 PM

Quote:

Originally Posted by dwhitney67 (Post 4586069)
Presumably, when a ball is thrown, there's someone else to catch it. It's the same concept when dealing with exceptions... if one is thrown, then somewhere in the code, it should be caught.

Try augmenting your code to have the following construct:
Code:

...

try
{
  throw Error("Any error");
}
catch (std::exception& e)
{
  std::cout << e.what() << std::endl;
}

...


yes sire, this is very obvious code fragments which i had not put in my post. It does not even come to catch() block. It just fails during throw Error("Any error"). However, it works fine if the shared library had been compiled on 32 bit server. This is an issue regarding Cross compilation. It has something to do with this Error class.

Anyways, Thanks for your reply.

gaurav.rustagi 01-27-2012 02:24 PM

Quote:

Originally Posted by NevemTeve (Post 4586173)
Are you sure that it is okay to use C++ from JNI?


Yes, That is the use of JNI, to call native libraries. In this case, the native library is written in C++.

NevemTeve 01-27-2012 03:47 PM

Thanks (back in my times JNI meant C, not C++).

gaurav.rustagi 01-27-2012 03:55 PM

Quote:

Originally Posted by NevemTeve (Post 4586236)
Thanks (back in my times JNI meant C, not C++).

I mean the native functions are C type only, but inside that code you can use class features.

dwhitney67 01-28-2012 07:51 AM

Quote:

Originally Posted by gaurav.rustagi (Post 4586189)
... It does not even come to catch() block. It just fails during throw Error("Any error"). However, it works fine if the shared library had been compiled on 32 bit server. This is an issue regarding Cross compilation. It has something to do with this Error class.

Through some experimentation, I was able to get the following code to work, under separate environments (32-bit and 64-bit), however I was unable to use the -m32 option on my 64-bit system; presumably this system is missing some critical development files.

Native.java:
Code:

import java.util.*;

class Native
{
  native public void function();

  static {
      System.loadLibrary("Native");
  }

  public static void main(String[] args)
  {
      try {
        Native nat = new Native();
        nat.function();
      }
      catch (Throwable e) {
        System.out.println("Java exception handled; cause: " + e);
      }
  }
}

Native.cpp:
Code:

#include <jni.h>
#include <stdexcept>
#include <string>
#include <iostream>

#include "Native.h"


class Error : public std::exception
{
public:
  Error(const std::string& message) : msg(message) {}

  virtual ~Error() throw() {}

  const char* what() const throw() { return msg.c_str(); }

private:
  std::string msg;
};


JNIEXPORT void JNICALL Java_Native_function(JNIEnv* env, jobject jobj)
{
  try
  {
      throw Error("Any error");
  }
  catch (std::exception& e)
  {
      std::cout << "C++ exception handled; cause: " << e.what() << std::endl;

      jclass exceptionClass = env->FindClass("java/lang/IllegalArgumentException");

      if (exceptionClass)
      {
        env->ThrowNew(exceptionClass, e.what());
      }
  }
}

I used the following Makefile to build and run the code:
Code:

JAVA_SRCS = Native.java
JAVA_CLAS = $(JAVA_SRCS:.java=)

CXX_SRCS  = Native.cpp
CXX_OBJS  = $(CXX_SRCS:.cpp=.o)

JNI_LIB  = libNative.so

JAVAC    = /usr/bin/javac
JAVAH    = /usr/bin/javah
JAVA      = /usr/bin/java

JVM_HOME  = /usr/lib/jvm/java-6-sun-1.6.0.26

ARCH      =
INCLUDES  = -I/usr/lib/jni -I$(JVM_HOME) -I$(JVM_HOME)/include -I$(JVM_HOME)/include/linux
CXXFLAGS  = $(INCLUDES) -c -Wall -pedantic -fPIC $(ARCH)

.PHONY: all clean


all : bld_java bld_jni bld_lib run

bld_java :
        @ echo Compiling $(JAVA_SRCS)
        @ $(JAVAC) $(JAVA_SRCS)

bld_jni :
        @ echo Building JNI Header File
        @ $(JAVAH) $(JAVA_CLAS)

bld_lib : $(CXX_OBJS)
        @ echo Building JNI Library
        @ $(CXX) -shared -o $(JNI_LIB) $^

%.o : %.cpp
        @ echo Compiling $<
        @ $(CXX) $(CXXFLAGS) $<

run :
        @ echo Running $(JAVA_CLAS)
        @ echo
        @ LD_LIBRARY_PATH=./:${LD_LIBRARY_PATH} $(JAVA) $(JAVA_CLAS)

clean :
        $(RM) $(CXX_OBJS) $(JNI_LIB)
        $(RM) $(JAVA_CLAS).class $(JAVA_CLAS).h

I hope this helps.

gaurav.rustagi 01-28-2012 10:53 PM

Quote:

Originally Posted by dwhitney67 (Post 4586691)
Through some experimentation, I was able to get the following code to work, under separate environments (32-bit and 64-bit), however I was unable to use the -m32 option on my 64-bit system; presumably this system is missing some critical development files.

Native.java:
Code:

import java.util.*;

class Native
{
  native public void function();

  static {
      System.loadLibrary("Native");
  }

  public static void main(String[] args)
  {
      try {
        Native nat = new Native();
        nat.function();
      }
      catch (Throwable e) {
        System.out.println("Java exception handled; cause: " + e);
      }
  }
}

Native.cpp:
Code:

#include <jni.h>
#include <stdexcept>
#include <string>
#include <iostream>

#include "Native.h"


class Error : public std::exception
{
public:
  Error(const std::string& message) : msg(message) {}

  virtual ~Error() throw() {}

  const char* what() const throw() { return msg.c_str(); }

private:
  std::string msg;
};


JNIEXPORT void JNICALL Java_Native_function(JNIEnv* env, jobject jobj)
{
  try
  {
      throw Error("Any error");
  }
  catch (std::exception& e)
  {
      std::cout << "C++ exception handled; cause: " << e.what() << std::endl;

      jclass exceptionClass = env->FindClass("java/lang/IllegalArgumentException");

      if (exceptionClass)
      {
        env->ThrowNew(exceptionClass, e.what());
      }
  }
}

I used the following Makefile to build and run the code:
Code:

JAVA_SRCS = Native.java
JAVA_CLAS = $(JAVA_SRCS:.java=)

CXX_SRCS  = Native.cpp
CXX_OBJS  = $(CXX_SRCS:.cpp=.o)

JNI_LIB  = libNative.so

JAVAC    = /usr/bin/javac
JAVAH    = /usr/bin/javah
JAVA      = /usr/bin/java

JVM_HOME  = /usr/lib/jvm/java-6-sun-1.6.0.26

ARCH      =
INCLUDES  = -I/usr/lib/jni -I$(JVM_HOME) -I$(JVM_HOME)/include -I$(JVM_HOME)/include/linux
CXXFLAGS  = $(INCLUDES) -c -Wall -pedantic -fPIC $(ARCH)

.PHONY: all clean


all : bld_java bld_jni bld_lib run

bld_java :
        @ echo Compiling $(JAVA_SRCS)
        @ $(JAVAC) $(JAVA_SRCS)

bld_jni :
        @ echo Building JNI Header File
        @ $(JAVAH) $(JAVA_CLAS)

bld_lib : $(CXX_OBJS)
        @ echo Building JNI Library
        @ $(CXX) -shared -o $(JNI_LIB) $^

%.o : %.cpp
        @ echo Compiling $<
        @ $(CXX) $(CXXFLAGS) $<

run :
        @ echo Running $(JAVA_CLAS)
        @ echo
        @ LD_LIBRARY_PATH=./:${LD_LIBRARY_PATH} $(JAVA) $(JAVA_CLAS)

clean :
        $(RM) $(CXX_OBJS) $(JNI_LIB)
        $(RM) $(JAVA_CLAS).class $(JAVA_CLAS).h

I hope this helps.

This is quite kind of you to do this experimentation. I really appreciate that. However, i am facing this problem because the shared library is compiled with -m32 option on 64 bit systems. You need to install glibc-devel.i686 (any version) package on your system. I too faced this issue in the begining. After this, probably you can try and run this program to replicate the issue. I will also try and do that.

gaurav.rustagi 01-30-2012 06:11 AM

Quote:

Originally Posted by gaurav.rustagi (Post 4587168)
This is quite kind of you to do this experimentation. I really appreciate that. However, i am facing this problem because the shared library is compiled with -m32 option on 64 bit systems. You need to install glibc-devel.i686 (any version) package on your system. I too faced this issue in the begining. After this, probably you can try and run this program to replicate the issue. I will also try and do that.

Hi all,

I have been able to resolve this issue. I had some .c source files where gcc is used instead of g++ for compilation. Now, It seems that i missed to have -m32 option in the configuration of make files used for .c files and i had hided warning messages with -w option in all the makefiles. As a result, i could not see what was going on during the compilation.

I have corrected these mistakes and now i can see it working fine.

Thanks for you help guys.


All times are GMT -5. The time now is 09:34 AM.