I'm using c++ builder 10.2 with the clang compiler on Windows 10 pro. Can anyone tell me why this doesn't compile?
// crt_tzset.cpp
// This program uses _tzset to set the global variables
// named _daylight, _timezone, and _tzname. Since TZ is
// not being explicitly set, it uses the system time.
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
_tzset();
int daylight;
_get_daylight( &daylight );
printf( "_daylight = %d\n", daylight );
long timezone;
_get_timezone( &timezone );
printf( "_timezone = %ld\n", timezone );
size_t s;
char tzname[100];
_get_tzname( &s, tzname, sizeof(tzname), 0 );
printf( "_tzname[0] = %s\n", tzname );
exit( 0 );
}
I get 3 'Unresolved external' errors relating to _get_daylight, _get_timezone and _get_tzname.
Since I don't have "c++builder", I tried this with MinGW.
With a straightforward compile and link command like this:
gcc -Wall -Werror -pedantic -O2 tz.c -o tz
I got the same errors:
C:\Users\###\AppData\Local\Temp\ccI8j8Mj.o:tz.c:(.text.startup+0x1f): undefined reference to `__imp__get_daylight'
C:\Users\###\AppData\Local\Temp\ccI8j8Mj.o:tz.c:(.text.startup+0x3a): undefined reference to `__imp__get_timezone'
C:\Users\###\AppData\Local\Temp\ccI8j8Mj.o:tz.c:(.text.startup+0x61): undefined reference to `__imp__get_tzname'
collect2.exe: error: ld returned 1 exit status
A single grep revealed the library libucrtbase.a (among others) to contain the symbol _get_daylight. Adding this library to the command:
gcc -Wall -Werror -pedantic -O2 tz.c -lucrtbase -o tz
This produced a runnable program.
The other libraries are all libmsvcr*.a in different versions, I tried just one of them. This was successful, too.
Edit:
With a not-so-current "clang" I didn't even need to add the library.
clang -Wall -Werror -pedantic -O3 tz.c -o tz-clang.exe
This compiled and linked without any error and runs perfectly.
(clang version 7.0.1 (tags/RELEASE_701/final), Target: x86_64-pc-windows-msvc)
Related
I have a mini project with two files:
main.cpp
#include <string>
template<int I>
int getint(int i)
{
extern std::string var;
return var.size() * i;
}
int main()
{
return getint<2>(2);
}
and sub.cpp
#include <string>
extern std::string var;
std::string var = "Hello";
But when I compile the project, the linker gives the error:
-------------- Clean: Debug in test (compiler: GNU GCC Compiler)---------------
Cleaned "test - Debug"
-------------- Build: Debug in test (compiler: GNU GCC Compiler)---------------
mingw32-g++.exe -Wall -fexceptions -g -c C:\Users\Fan\Downloads\test\test\main.cpp -o obj\Debug\main.o
mingw32-g++.exe -Wall -fexceptions -g -c C:\Users\Fan\Downloads\test\test\sub.cpp -o obj\Debug\sub.o
mingw32-g++.exe -o bin\Debug\test.exe obj\Debug\main.o obj\Debug\sub.o
obj\Debug\main.o: In function `Z6getintILi2EEii':
C:/Users/Fan/Downloads/test/test/main.cpp:6: undefined reference to `var'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second(s))
2 error(s), 0 warning(s) (0 minute(s), 0 second(s))
I have no clue how this happens, because as long as I simplified the program a little, the problem goes away.
If I make getint() a plain old function instead of a function template, then the compilation succeeds.
If I move the line "extern std::string var;" outside the function (say to one line above it), then the compilation succeeds.
If I change the type of var to an int (and omit ".size()" in main.cpp, and assign 1 to it in sub.cpp), then the compilation succeeds.
It seems a weird combination of factors that prevent my original project from compiling. I have no idea what they are :(
Edit: In response to the "cannot reproduce" remark, I am trying the compilation on my local windows 7 machine using Code::Blocks 17.12. Output of the compiler and the linker has been updated to include compiler flags.
Edited: ODR violation fixed.
Edited: I found that reordering the link directories (-L) fixed the problem but I don't know why.
The original order in the g++ command that was causing the problem was this:
-L/usr/local/lib
-L/usr/local/lib64
-L/usr/lib
-L/usr/lib/64
-L../../bin/Release
Moving -L../../bin/Release which contains the VampEngine.so fixed the problem, but why?
Edited Ends Here
I have two projects. VampEngine (A shared lib) and Application (the client). When I compile both of them on Windows (visual c++), VampEngine links just fine with the Application but on Linux I get undefined errors (g++).
I checked if the correct flags and paths are passed in the compiler's arguments and it seem right.
Also I'm pretty positive that I use extern "C" in both the dll implementation and in the client's decelerations.
Here is analytically the g++ makefile execution:
-------------- Clean: Debug|x64 in VampEngine (compiler: GNU GCC Compiler)---------------
Cleaned "VampEngine - Debug|x64"
-------------- Clean: Debug|x64 in Application (compiler: GNU GCC Compiler)---------------
Cleaned "Application - Debug|x64"
-------------- Build: Debug|x64 in VampEngine (compiler: GNU GCC Compiler)---------------
g++ -m64 -fPIC -I../../Depedencies/Cross-Plat/glm-0.9.9.5 -I/usr/include -I/usr/local/include -c /home/babaliaris/Deve/cpp/VampEngine/VampEngine/src/core.cpp -o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/core.o
g++ -m64 -fPIC -I../../Depedencies/Cross-Plat/glm-0.9.9.5 -I/usr/include -I/usr/local/include -c /home/babaliaris/Deve/cpp/VampEngine/VampEngine/src/stb_image/stb_image.cpp -o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/stb_image/stb_image.o
g++ -m64 -fPIC -I../../Depedencies/Cross-Plat/glm-0.9.9.5 -I/usr/include -I/usr/local/include -c /home/babaliaris/Deve/cpp/VampEngine/VampEngine/src/window.cpp -o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/window.o
g++ -shared -L/usr/lib -L/usr/lib64 -L/usr/local/lib -L/usr/local/lib64 ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/core.o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/stb_image/stb_image.o ../../bin-int/Debug/VampEngine/x64/Debug/VampEngine/VampEngine/src/window.o -o ../../bin/Debug/libVampEngine.so -s -shared -m64 -L/usr/lib64 -lGL -lGLEW -lglfw
Output file is ../../bin/Debug/libVampEngine.so with size 138.57 KB
-------------- Build: Debug|x64 in Application (compiler: GNU GCC Compiler)---------------
g++ -m64 -I../../Depedencies/Cross-Plat/glm-0.9.9.5 -I../../VampEngine/src -I/usr/include -I/usr/local/include -c /home/babaliaris/Deve/cpp/VampEngine/Application/src/main.cpp -o ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o
g++ -L/usr/lib -L/usr/lib64 -L/usr/local/lib -L/usr/local/lib64 -L../../bin/Debug -o ../../bin/Debug/Application ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o -s -m64 -L/usr/lib64 -lVampEngine
/usr/bin/ld: ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o: in function `VampEngine::Core::Core(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int, unsigned int)':
main.cpp:(.text._ZN10VampEngine4CoreC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjj[_ZN10VampEngine4CoreC5ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjj]+0x31): undefined reference to `Vamp_Core_Constructor'
/usr/bin/ld: ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o: in function `VampEngine::Core::~Core()':
main.cpp:(.text._ZN10VampEngine4CoreD2Ev[_ZN10VampEngine4CoreD5Ev]+0x17): undefined reference to `Vamp_Core_Deconstructor'
/usr/bin/ld: ../../bin-int/Debug/VampEngine/x64/Debug/Application/Application/src/main.o: in function `VampEngine::Core::MainLoop()':
main.cpp:(.text._ZN10VampEngine4Core8MainLoopEv[_ZN10VampEngine4Core8MainLoopEv]+0x17): undefined reference to `Vamp_Core_MainLoop'
collect2: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 1 second(s))
4 error(s), 0 warning(s) (0 minute(s), 1 second(s))
Here is the core.cpp file which contains the implementation of the extern functions in the shared library:
#include "core.h"
#include "window.h"
#include <GLFW/glfw3.h>
#include "Engine/API.h"
namespace VampEngine
{
CoreImpl::CoreImpl(std::string title, unsigned int width, unsigned int height)
: window( new WindowImpl(title, width, height) )
{
}
CoreImpl::~CoreImpl()
{
delete window;
}
void CoreImpl::MainLoop()
{
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window->m_window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window->m_window);
/* Poll for and process events */
glfwPollEvents();
}
}
}
extern "C" VAMP_API void* Vamp_Core_Constructor(const char* title, unsigned int width, unsigned int height)
{
return new VampEngine::CoreImpl(title, width, height);
}
extern "C" VAMP_API void Vamp_Core_Deconstructor(void* obj)
{
VampEngine::CoreImpl *object = (VampEngine::CoreImpl*)obj;
delete object;
}
extern "C" VAMP_API void Vamp_Core_MainLoop(void* obj)
{
VampEngine::CoreImpl* object = (VampEngine::CoreImpl*)obj;
object->MainLoop();
}
And this is the core.hpp which the client includes and compiles in his main.cpp file:
#ifndef VAMP_ENGINE_CORE_HPP
#define VAMP_ENGINE_CORE_HPP
#include <Engine/API.h>
#include <iostream>
extern "C"
{
VAMP_API void* Vamp_Core_Constructor(const char* title, unsigned int width, unsigned int height);
VAMP_API void Vamp_Core_Deconstructor(void* obj);
VAMP_API void Vamp_Core_MainLoop(void* obj);
}
namespace VampEngine
{
class Core
{
private:
void* m_core;
public:
Core(std::string title, unsigned int width, unsigned int height)
: m_core(Vamp_Core_Constructor(title.c_str(), width, height))
{
}
~Core()
{
Vamp_Core_Deconstructor(m_core);
}
void MainLoop()
{
Vamp_Core_MainLoop(m_core);
}
};
}
#endif
The VAMP_API macro is empty when compiled on Linux.
#ifndef VAMP_ENGINE_API_H
#define VAMP_ENGINE_API_H
//On Windows Platforms.
#ifdef VAMP_PLATFORM_WINDOWS
#ifdef VAMP_BUILD_DLL
#define VAMP_API _declspec(dllexport)
#else
#define VAMP_API _declspec(dllimport)
#endif
//Unix-Based Systems (GCC).
#else
#define VAMP_API
#endif
#endif
As you can see I use exactly the same names.
So what else can cause an undefined error?
I use arch linux x64, with gcc version:
$gcc --version
gcc (GCC) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Problem solved.
My code was just fine, the culprit was actually another libVampEngine.so library that was copied in /usr/lib by me. The linker was searching in the /usr/lib directory first and then the bin/ directory of my project, so instead of using the right .so file to link against, it was using the outdated one.
If anyone else is experiencing a problem like this and is almost certain that his code is fine, follow these steps:
1) Ensure that the linker is actually linking the correct shared library.
2) Check the library directories (-L) that the linker is searching for binaries.
-Make sure these directories do not contain a binary with the exact same name as
your own library.
3) Be carefull of outdated binary files. If the linker is linking against
one but your code has been updated, even if the program links correctly you will get
undefined behavior on runtime.
I have a problem while running an executable file with dlopen function used to open shared and sanitized library with a one simple function.
I use precompiled Clang 3.9.0 for Ubuntu 14.04.
My question is: Is it possible to run it properly, so I can look for undefined behavior errors in the library while running an executable ? If the answers is yes, then how ?
I have two files:
//simpledll.cpp
#include <cstdio>
int hehe(int argc) {
int k = 0x7fffffff;
k += argc;
return 0;
}
//dlopen.cpp
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main() {
void* handle;
handle = dlopen("simpledll.so", RTLD_LAZY);
if(!handle) {
fprintf(stderr, "%s\n", dlerror());
}
int (*function)(int) = reinterpret_cast<int (*)(int)> (dlsym(handle, "_Z4hehei"));
if (function == nullptr)
fprintf(stderr, "Nope\n");
else
function(1000); // this yields signed integer overflow
return 0;
}
I have tried to get it to work in two steps (both have failed)
Step I
Compile the executable with:
clang++ dlopen.cpp -ldl --std=c++11 -o dlopen
Compile the library with:
clang++ -fsanitize=undefined -shared -o simpledll.so -fPIC simpledll.cpp
Result:
./dlopen: symbol lookup error: simpledll.so: undefined symbol: __ubsan_handle_add_overflow
Step II (idea from this forum)
Compile the executable as in Step I,
Compile the library with:
clang++ -fsanitize=undefined -shared -Wl,--whole-archive -L/usr/local/lib/clang/3.9.0/lib/linux/ -lclang_rt.ubsan_standalone_cxx-x86_64 -Wl,--no-whole-archive -lclang_rt.ubsan_standalone-x86_64 -Wl,--no-whole-archive -o simpledll.so -fPIC simpledll.cpp
Result:
==11478==Sanitizer CHECK failed: /home/development/llvm/3.9.0/final/llvm.src/projects/compiler-rt/lib/ubsan/ubsan_init.cc:61 ((UBSAN_MODE_UNKNOWN)) != ((ubsan_mode)) (0, 0)
Note that in Step II, if we substitute the function in the shared library with the one that has no undefined behavior code, the program runs without a CHECK failed error. This indicates that UBSAN has found an undefined behavior code, however it was unable to report it properly.
Regards,
Jaszczur
I am currently using Boost 1.54.0. I am following the code from this example.
example_44_01.cpp
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
void wait(int seconds)
{
boost::this_thread::sleep_for(boost::chrono::seconds{seconds});
}
void thread()
{
for (int i = 0; i < 5; ++i)
{
wait(1);
std::cout << i << std::endl;
}
}
int main(int argc, char** argv)
{
boost::thread t{thread};
t.join();
return 0;
}
So, it looks like all I need is the -lboost_thread, and -lboost_chrono libraries to link to at compile time. I also added the -lboost_system.
Here are my execution scripts.
g++-7 -Wall -std=c++1z -g -c example_44_01.cpp -o example_44_01.o
g++-7 -Wall -std=c++1z -g example_44_01.o -o example_44_01 -lboost_system -lboost_thread -lboost_chrono &>result.txt
What's going on here? This is the result.txt file:
example_44_01.o: In function `boost::this_thread::sleep_for(boost::chrono::duration<long, boost::ratio<1l, 1000000000l> > const&)':
/usr/local/include/boost/thread/pthread/thread_data.hpp:243: undefined reference to `boost::this_thread::hidden::sleep_for(timespec const&)'
collect2: error: ld returned 1 exit status
I've compiled and linked other programs with the same libraries without error. So is the error in the code? This seems doubtful as the code is straight from the documentation. Any insight is appreciated.
I had this issue once because I was indeliberately using different versions of Boost (I had first installed Boost from commandline, then a few months later on, manually from zip).
Try adding the path to your Boost libraries to the compiler. For instance, if your libraries are stored at /usr/local/lib, try:
g++-7 -Wall -std=c++1z -g example_44_01.o -o example_44_01 -L/usr/local/lib -lboost_system -lboost_thread -lboost_chrono &>result.txt
I've been trying to compile with std::atomic, and I'm getting unresolved references to __atomic_load, __atomic_store, and __atomic_store_16.
I know in a later version of gcc (4.8+?) you include -latomic, but I'm compiling with gcc 4.7.3; I've tried adding -latomic_ops and -latomic_ops_gpl, but neither seem to do much.
I am installing gcc 4.8.1 now, but I do have a release platform that'll really need to be compiled for 4.7.3.
Many thanks.
Edit:
Ok, here's some code that results in the problem I have:
atomics.cpp
#include <atomic>
#include <stdint.h>
struct dataStruct {
int a;
uint16_t b;
float c;
dataStruct(int ai, uint16_t bi, float ci) noexcept : a(ai), b(bi), c(ci) {
}
dataStruct() noexcept : dataStruct(0,0,0) {
}
};
int main() {
std::atomic<dataStruct> atomicValue;
atomicValue = dataStruct(10, 0, 0);
return atomicValue.load().b;
}
With "g++-4.8.1 *.cpp -std=c++0x -latomic", this compiles fine.
With "g++-4.7.3 *.cpp -std=c++0x -pthread -lpthread -latomic_ops", it fails with the following:
/tmp/ccQp8MJ2.o: In function `std::atomic<dataStruct>::load(std::memory_order) const':
atomics.cpp:(.text._ZNKSt6atomicI10dataStructE4loadESt12memory_order[_ZNKSt6atomicI10dataStructE4loadESt12memory_order]+0x2f): undefined reference to `__atomic_load'
/tmp/ccQp8MJ2.o: In function `std::atomic<dataStruct>::store(dataStruct, std::memory_order)':
atomics.cpp:(.text._ZNSt6atomicI10dataStructE5storeES0_St12memory_order[_ZNSt6atomicI10dataStructE5storeES0_St12memory_order]+0x35): undefined reference to `__atomic_store'
collect2: error: ld returned 1 exit status
Ok, finally found the answer at: https://gcc.gnu.org/wiki/Atomic/GCCMM
Turns out, 4.7 did not in fact have 'official' atomics support (just the header files). If you want to use atomics in 4.7 compilers, you must download the source code linked on that page and build it yourself
gcc -c -o libatomic.o libatomic.c
ar rcs libatomic.a libatomic.o
Then, you can build it using
g++-4.7.3 -std=c++0x atomics.cpp -latomic -L./