I started my adventure with programming today and faced some troubles. While wiritng
#include <stdio.h>
main(void)
{
printf ("hello, world\n");
}
in C language on the website called cs50.io and then writing clang hello.c I've got following error:
Any ideas how to solve it?
First, you could find your answers already posted on StackOverflow. You should read your error messages, and then try to understand what they mean through your own searches.
undefined reference to 'main' error is explained here:
Undefined reference to main - collect2: ld returned 1 exit status
Essentially, in C language, void is not a valid return for main() function (i.e. void main(void)). With gcc compiler, which I think, is similar to clang, when main() has no specification, your return defaults to int. So, you have main() function with no return value, when a return is needed. Read this other StackOverflow Q & A for more information on valid signatures for C's main() function:
What are the valid signatures for C's main() function?
Since, I'm not familiar with clang compiler, there may be something else happening besides these errors.
As good practice, you will want to compile using flags to account for certain errors/warnings that you may have in your code but might be dismissed by the compiler.
-Werror is a great flag that counts all warnings as errors. You would recompile as clang -Werror hello.c
In this case, since you are just printing and not returning anything, you should have void main (void)
With the code you have provided, you should always account for what the function is returning as mentioned above.
Cheers.
Related
Having trouble finding a sufficiently precise answer, basically my compiler (GCC std=c++11) does recognise the type "Object".
Yes, I am fairly new to ++
Tried changing command line options, tried Googling for an exact solution.
If anyone spots any other potential issues, please do let me know. I am finding the NodeJS docs a bit ambiguous in some areas.
I have included my code and command line output.
Command line snippet:
g++ exampleMod.c -I/usr/include/c++/4.8.5 -I/lhome/psyjw21/node-v10.16.3-linux-x64/include/node -I /usr/include/c++/4.8.5/x86_64-redhat-linux -std=c++11
exampleMod.c:7:1: error: ‘Object’ does not name a type
Object obj = Object::New(env);
The code:
#define NAPI_VERSION 3
#include <node.h>
#include <node_buffer.h>
#include <node_version.h>
#include <node_object_wrap.h>
Object obj = Object::New(env);
obj["foo"] = String::New(env, "bar");
Never mind - I have found the problem.
I included what was meant to be part of the Javascript in my C++ file.
obj["foo"] - I kind of realised what I did when I saw I had used a string as an array index... that isn't going to work in C++! (actually, I need to check a few things because I didn't think you could do it Javascript either).
Anyway, yes, feel free to comment on what a dumb mistake this was....
I am trying to link a c program that I compiled with the gcc compiler. The linker does not find the symbol tdestroy which is a gnu extension to libc (#define __USE_GNU followed by #include <search.h>). Is there an additional library that I have to link with in order for the linker to find this symbol?
~Update~: I just realized that it does indeed link on my Linux environment but on Windows, I still get a undefined reference to 'tdestroy' error with mingw/gcc, even after using _GNU_SOURCE instead of __USE_GNU.
Don't use __USE_GNU. That's an internal GLIBc macro. The tdestroy man page says the macro you need
to define at the beginning is _GNU_SOURCE.
#define _GNU_SOURCE
#include <search.h>
void *td = tdestroy;
int main(){}
compiles with no linker error (no extra libraries needed).
You should never define __USE_GNU (sic), it is an internal symbol. You need to define _GNU_SOURCE, see Feature Test Macros.
If you do that, the tdestroy function will become available.
It is also a good idea to build with -Werror=implicit-function-declaration, so that missing prototypes lead to a compiler failure, and not later to a linker failure.
I have downloaded libgcrypt library source code and I want to customize this standard shared library by adding my function inside one particular
source code file .
Although compilation/build process of customized shared library is successful, but it shows error at linking time.
Here is what I have done .
inside /src/visibility.c file, I have added my custom function,
void MyFunction(void)
{
printf("This is added just for testing purpose");
}
I have also include function prototype inside /src/gcrypt.h
void MyFunction(void);
#build process
./configure --prefix=/usr
sudo make install
nm command find this custom function.
nm /usr/lib/libgcrypt.so | grep MyFunction
000000000000dd70 t MyFunction
Here is my sample code to access my custom function.
//aes_gcrypt_example.c
#include <stdio.h>
#include <gcrypt.h>
#include <assert.h>
int main()
{
MyFunction();
return 0;
}
gcc aes_gcrypt_example.c -o aes -lgcrypt
/tmp/ccA0qgAB.o: In function `main':
aes_gcrypt_example.c:(.text+0x3a2): undefined reference to `MyFunction'
collect2: error: ld returned 1 exit status
I also tried by making MyFunction as extern inside gcrypt.h, but in that case also I am getting same error.
Why is this happening ?
Is the customization of standard library is not allowed ?
If YES, then is there any FLAG to disable to allow customization ?
If NO, what mistake I am making ?
It would be great help if someone provide some useful link/solution for the above mentioned problem. I am using Ubuntu16.04 , gcc 4.9.
Lower-case t for the symbol type?
nm /usr/lib/libgcrypt.so | grep MyFunction
000000000000dd70 t MyFunction
Are you sure that's a visible function? On my Ubuntu 16.04 VM, the linkable functions defined in an object file have T (not t) as the symbol type. Is there a stray static kicking around and causing confusion? Check a couple of other functions defined in libgcrypt.so (and documented in gcrypt.h) and see whether they have a t or a T. They will have a T and not t. You'll need to work out why your function gets a t — it is not clear from the code you show.
The (Ubuntu) man page for nm includes:
The symbol type. At least the following types are used; others
are, as well, depending on the object file format. If lowercase,
the symbol is usually local; if uppercase, the symbol is global
(external).
The line you show says that MyFunction is not visible outside its source file, and the linker agrees because it is not finding it.
Your problem now is to check that the object file containing MyFunction has a symbol type T — if it doesn't the problem is in the source code.
Assuming that the object file shows symbol type T but the shared object shows symbol type t, you have to find what happens during the shared object creation phase to make the symbol invisible outside the shared object. This is probably because of a 'linker script' that controls which symbols are visible outside the library (or maybe just compilation options). You can search on Google with 'linker script' and various extra words ('tutorial', 'provide', 'example', etc) and come up with links to the relevant documentation.
You may need to research documentation for LibTool, or for the linker BinUtils. LibTool provides ways of manipulating shared libraries. In a compilation command line that you show in a comment, there is the option -fvisibility=hidden. I found (mostly by serendipitous accident) a GCC Wiki on visibility. See also visibility attribute and code generation options.
I have a code A that is statically linked against one version of mpich. Now comes library B, which is used by A via dlopen(). B depends on mpich as well, but is linked dynamically against it.
The problem is that now, in order for B to take advantage of mpi distribution, needs to access the communicator currently handled by A. This communicator has been created by A static version of mpich, When B invokes MPI routines, it will use a dynamic version of MPI which is not guarateed to be compatible with the static version attached to A.
This is the overall picture. I think that the only solution is to have mpich dynamically linked for both A and B. What I am not fully understanding is however the following:
how does the linker handle shared objects dependencies when dlopening? Will I have two instances of mpich in VM also with dynamic linking, or is the linker smart enough to realize that the symbols required by the dlopened B are already in the address space and will resolve against those.
Is it possible to tell the linker: when you dlopen this library, don't go fetch the dynamic dependency, but resolve it with the static symbols that are already provided by A
In short: it depends on dlopen options. By default, if a symbol needed by the requested library already exists in the global scope, it will be reused (this is what you want). But you can bypass this behavior with RTLD_DEEPBIND, with this flag, the dependencies won't be reused from the global scope, and will be loaded a second time.
Here is some code to reproduce your situation and demo the effect of this flag.
Let's make a common library that will be used by both lib A and program B. This library will exist in two versions.
$ cat libcommon_v1.c
int common_func(int a)
{
return a+1;
}
$ cat libcommon_v2.c
int common_func(int a)
{
return a+2;
}
Now let's write lib A that uses libcommon_v2:
$ cat liba.c
int common_func(int a);
int a_func(int a)
{
return common_func(a)+1;
}
And finally program B that dynamically links to libcommon_v1 and dlopens lib A:
$ cat progb.c
#include <stdio.h>
#include <dlfcn.h>
int common_func(int a);
int a_func(int a);
int main(int argc, char *argv[])
{
void *dl_handle;
int (*a_ptr)(int);
char c;
/* just make sure common_func is registered in our global scope */
common_func(42);
printf("press 1 for global scope lookup, 2 for deep bind\n");
c = getchar();
if(c == '1')
{
dl_handle = dlopen("./liba.so", RTLD_NOW);
}
else if(c == '2')
{
dl_handle = dlopen("./liba.so", RTLD_NOW | RTLD_DEEPBIND);
}
else
{
printf("wrong choice\n");
return 1;
}
if( ! dl_handle)
{
printf("dlopen failed: %s\n", dlerror());
return 2;
}
a_ptr = dlsym(dl_handle, "a_func");
if( ! a_ptr)
{
printf("dlsym failed: %s\n", dlerror());
return 3;
}
printf("calling a_func(42): %d\n", (*a_ptr)(42));
return 0;
}
Let's build and run all the things:
$ export LD_LIBRARY_PATH=.
$ gcc -o libcommon_v1.so -fPIC -shared libcommon_v1.c
$ gcc -o libcommon_v2.so -fPIC -shared libcommon_v2.c
$ gcc -Wall -g -o progb progb.c -L. -lcommon_v1 -ldl
$ gcc -o liba.so -fPIC -shared liba.c -L. -lcommon_v2
$ ./progb
press 1 for global scope lookup, 2 for deep bind
1
calling a_func(42): 44
$ ./progb
press 1 for global scope lookup, 2 for deep bind
2
calling a_func(42): 45
We can clearly see that with default options, dlopen reuses the symbol common_func that was present in program B and that with RTLD_DEEPBIND, libcommon was loaded again and library A got its own version of common_func.
You did not say which Toolchain (GCC, LLVM, MSC, etc.) you are using, the most helpful answer will depend upon this information.
May I suggest you look at "GCC Exception Frames" http://www.airs.com/blog/archives/166 .
If that is helpful then the Gold Linker, which is available for GCC and LLVM, supports 'Link Time Optimization' and can run in "Make" with DLLTool http://sourceware.org/binutils/docs/binutils/dlltool.html .
Indeed it is possible to have both Static and Dynamic Code call each other, the Computer does not care; it will 'run' anything it is fed -- whether that ends up working exactly the way you want or HCFs depends on correct Code and correct Linker commands.
Using a Debugger will not be fun. It would be best to mangle the names prior to Linking so that when debugging you can see from which module the Code came. Once it is up and running you can undef the Mangle and have the same-named Functions Link (to ensure it still functions).
Compiler / Linker Bugs will not be your friend.
This sort of scenario (Static and Dynamic Linking) occurs more often with MinGW and Cygwin where some of the Libraries are Static yet a Library you download from the Internet is only available in Dynamic form (without Source).
If the Library is from two different Compiler Toolchains then other issues arise, see this StackOverflow Thread: " linking dilemma (undefined reference) between MinGW and MSVC. MinGW fails MSVC works ".
It would be best to simply get the newest version of the Library from the source and compile the whole thing yourself, rather than rely on trying to cobble together bits and pieces from different sources (though it is possible to do that).
You can even load the Dynamic Library and call it (statically) and then reload portions of it later.
How tight are you on Memory and how fast do you want Functions to run, if everything is in Memory your Program can transfer execution to called Functions straight away, if you are swapping a portion of your Code to VM your execution times will really take a hit.
Running a Profiler on your Code will help decide what portions of a Library to load if you want to do 'dynamic dynamic linking' (full control of your dyna-linking by loading a Dynamic Library so it can be used Statically). This is the stuff that headaches and nightmare are made of. GL.
I have a file with the void initGui() function in it. It does stuff.
I also have a .so shared library made with that file.
The problem is, when I try to launch a dlsym(..., "initGui"), dlerror() tells me that it didn't found the symbol (of course, I used dlopen to open it). So I tried to nm my shared lib. I "understood" that _Z7initGuiiii might be what I'm looking for. So I tried to dlsym it ... And it worked.
Please can someone tell me how to have clean symbols in my shared object library ?
I compile with g++ -Wall -Wextra -Werror -c -fPIC.
The usual practice when dlsym-ing inside some dlopen-ed shared library coded in C++ is to have the convention that those seeked symbols (those that you are dlsym-ing) are declared extern "C". Then their name is easily visible with dlsym. So you need to declare
extern "C" void initGui(void);
and then to do
typedef void initguiroutine_sig_t(void);
initguiroutine_sig_t* initguiptr = dlsym(dlhandle,"initGui");
if (!initguiptr) {
fprintf(stderr, "initGui not found: %s\n", dlerror());
exit (EXIT_FAILURE);
};
// later, call initguiptr like
(*initguiptr) ();
I don't recommend understanding in great details how your C++ name mangling works, it is not very well defined, and details depend upon particular version of the C++ libraries (notably the standard C++ library) and of the compiler version.