views:

83

answers:

3

I am new to linux, while compiling with dynamic library I am getting the segmentationfault error.

I have two files

ctest1.c

void ctest1(int *i)
{ 
   *i =10;
}

ctest2.c

void ctest2(int *i)
{ 
   *i =20;
}

I have compiled both files to a shared library named libtest.so using following command

  gcc -shared -W1,-soname,libtest.so.1 -o libtest.so.1.0.1 ctest1.o ctest2.o -lc

And I have wrote another program prog.c which uses functions exported by this library

prog.c

#include <stdio.h>

void (*ctest1)(int*);
void (ctest2)(int*);


int main()
{
  int a;

  ctest1(&a);

  printf("%d",a);

  return 0;

}

And when I have built the executable with following command

gcc -Wall prog.c -L. -o prog

But when I run the generated executable I get the SegmentationFault error.

When I checked the header of prog with ldd it shows

linux-vdso.so.1 => (0x00007f99dff000) libc.so.6 => /lib64/libc.so.6 (0x0007feeaa8c1000) /lib64/ld-linux-x86-64.so.2 (0x00007feeaac1c000)

Can somebody tell what is the problem

+6  A: 

You aren't calling into ctest1.c or ctest2.c. Instead, you're creating ctest1 and ctest2 function pointers in prog.c, which you are not initializing, so it is causing a segmentation fault when you try to call them.

You need to declare your functions so prog.c can see them, and then link prog.c to the libraries (probably using the -l option to gcc).

#include <stdio.h>

extern void ctest1(int*);
extern void ctest2(int*);


int main()
{
  int a;

  ctest1(&a);

  printf("%d",a);

  return 0;

}

And something like:

gcc -Wall -L. -ltest prog.c -o prog
WhirlWind
you can extern void ctest1(int*);void ctest2(int*); and link your library.. it should work
subbul
@WhirlWind Ater making the above changes I am getting the error "cannot find -ltest" .
siri
@Sirish - try building your shared library using something simple like "gcc -shared -o libtest.so ctest1.c ctest2.c" -- that worked for me.
WhirlWind
@WhirlWind I have declared the functions as extern in prog.c and build the shared library as you mentioned , but still i get the segmentation fault
siri
The declaration `void (ctest2)(int *);` is just a funny way of writing `extern void ctest2(int *);` which has the merit of overriding any function-like macro `ctest2` because the name is not followed by an open parenthesis. The definition of `ctest1` is a function pointer which is not initialized and hence causes the seg fault.
Jonathan Leffler
@Jonathan Leffler @WhirlWind Yes I was wrong, it solved the seg fault. Thank You.
siri
A: 

.so libraries in linux are dynamically linked. You will need to open the .so file using dlopen() in prog.c, find the symbols and then call ctest1() and ctest2() via function pointers.

Sid H
+1  A: 

Try this after using the information WhirlWind gave you (the lines beginning with '#' are comments; you don't need to type them):

# Ensure that any shared objects you use are available in the current directory.
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

# Compile the library with a real name of "libctest.so.1.0.1"
# and a soname of "libctest.so.1".
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0.1 ctest1.o ctest2.o

# Create a symbolic link with soname as the name that points to the library.
# (libctest.so.1 -> libctest.so.1.0.1)
/sbin/ldconfig -v -n .

# Create a symbolic link using the "linker name" that points to the newly
# created library.
ln -sf libctest.so.1 libctest.so

# Compile your program.
gcc -Wall -L. prog.c -o prog -l ctest

# Run your program (it won't work without setting LD_LIBRARY_PATH because
# it won't be able to find your library).
./prog

That worked for me. It's a lot of work seemingly, but after a few trial-and-error cases, I think it becomes almost routine.

You can find some more information at http://www.ibm.com/developerworks/library/l-shobj/. :)

Edit: I almost forgot to mention that it seems a lot of tutorials suggest using the -fPIC option to generate position-independent code (don't confuse it with -fpic since that can make your resulting library less portable). It couldn't hurt to have it, but for simplicity I omitted it from the lines above.

Dustin