Undefined reference error when trying to include header from same project - c++11

I have a method I've defined like this:
int generate(const char* infile, std::vector<uint8_t> &detection, int another_flag);
I wanted detection to be a reference to the vector passed into it (hence the &), so that changes in this method happens to the original and hang around when the method exits.
I've built that method into a shared library. In the same project I've written a test program that imports the header:
#import <extract.hpp>
In the test program I'm calling the method like this:
const char* infile = argv[1];
std::vector<uint8_t> detection;
int ret;
ret = generate(infile, detection, 0);
It compiles, but it won't link, complaining:
undefined reference to `generate(char const*, std::vector<unsigned char, std::allocator<unsigned char> >&, int)'
I'm attempting to build the project using cmake.
The entry for the test file is as follows:
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) <-- the location of extract.hpp
add_executable(harness harness.cpp)
target_include_directories(harness PRIVATE include) <-- desperate attempt
target_link_libraries(harness ${CV_LIBS})
This file is referenced from another CMakeLists file using an add_subdirectory(test) command.
What am I doing wrong?

We just found it wasn't linking the library. Apparently it needed to get added to the target_link_libraries call so it would be:
target_link_libraries(harness ${CV_LIBS} extract)

Related

C++ templates reading type from configuration file at runtime

I've been trying to write a piece of code that reads a configuration file at runtime, and this file contains the names of different variables, and their type. These types are almost all builtin (int, unsigned int, char*, unsigned long long, float), with the exception of one class which stores information as binary flags.
Example configuration file contains:
Name std::string Measurement
PositionX float 0.004
PositionY float 0.002
Time unsigned long long 1521479000
Function which needs this information:
std::vector<float> xPos;
...
while( loops_over_a_file_containing_values );
...
xPos.push_back(get_information["PositionX"].extract<float>());
However, I cannot for the life of me seem to find a method in which to define these in a C++ code, most of my googling leads me to "This doesn't work" or answers that are so complicated to me that I cannot implement it in a reasonable way.
The main reason behind this is because there are a rather large number of variables with different types, and their type is needed as this function comes from another user written C++ package (which I have no way to modify in any shape or form).
So far I've looked at boost::any, boost::variant but I can't see how this could be done with those. And I'm unsure how exactly to go about this with templates either, I've tried:
template <int ModeDecider> class TypeDecider{ };
template <> class TypeDecider<0>{ public: typedef int Type; };
template <> class TypeDecider<1>{ public: typedef unsigned int Type; };
template <> class TypeDecider<2>{ public: typedef unsigned long long Type; };
template <> class TypeDecider<3>{ public: typedef float Type; };
...
std::string test1 = "unsigned long long";
std::string test2 = "1521479000";
switch( test1 ){
...
std::vector<TypeDecider<2>::Type> testvec;
testvec.push_back(static_cast<TypeDecider<2>::Type>(test2));
...}
But this gives me:
cannot convert 'std::__cxx11::string' (aka 'basic_string<char>') to 'TypeDecider<2>::Type' (aka 'unsigned long long') without a conversion operator
Which I'm not exactly sure how to go about fixing. And so far my googling-fu has yielded very little. As such, I'm here asking for help before I go to the awful step of writing a Python script in order to write the C++ script.

No member named value in std::is_convertible when using clang

In a very simple situation with a constrained constructor, testing for convertibility of the argument, an error is produced in clang, but not in g++:
#include <type_traits>
template <class T, class U>
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
template <class T>
struct A
{
template <class S, class = std::enable_if_t<Convertible<S,T>> >
A(S const&) {}
};
int main()
{
A<double> s = 1.0;
}
Maybe this issue is related to Is clang's c++11 support reliable?
The error clang gives, reads:
error: no member named 'value' in 'std::is_convertible<double, A<double> >'
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
~~~~~~~~~~~~~~~~~~~~~~~~~~^
I've tried
g++-5.4, g++-6.2 (no error)
clang++-3.5, clang++-3.8, clang++-3.9 (error)
with argument -std=c++1y and for clang either with -stdlib=libstdc++ or -stdlib=libc++.
Which compiler is correct? Is it a bug in clang or gcc? Or is the behavior for some reasons undefined and thus both compilers correct?
First of all, note that it works fine if you use:
A<double> s{1.0};
Instead, the error comes from the fact that you are doing this:
A<double> s = 1.0;
Consider the line below (extracted from the definition of Convertible):
std::is_convertible<U,T>::value
In your case, this is seen as it follows (once substitution has been performed):
std::is_convertible<double, A<double>>::value
The compiler says this clearly in the error message.
This is because a temporary A<double> is constructed from 1.0, then it is assigned to s.
Note that in your class template you have defined a (more or less) catch-all constructor, so a const A<double> & is accepted as well.
Moreover, remember that a temporary binds to a const reference.
That said, the error happens because in the context of the std::enable_if_t we have that A<double> is an incomplete type and from the standard we have this for std::is_convertible:
From and To shall be complete types [...]
See here for the working draft.
Because of that, I would say that it's an undefined behavior.
As a suggestion, you don't need to use std::enable_if_t in this case.
You don't have a set of functions from which to pick the best one up in your example.
A static_assert is just fine and error messages are nicer:
template <class S>
A(S const&) { static_assert(Convertible<S,T>, "!"); }

Neither ld wrap nor LD_PRELOAD working to intercept system call

I am trying to use -Wl, -wrap=sendto -Wl, -wrap, sendto in my final g++ link command that links my app to replace the standard sendto function with my own.
I compile the following source code with:
gcc -c -o wrap.o wrap.c
and include the wrap.o in the final g++ command that links the app (the rest of the app is C++ hence the use of g++):
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
ssize_t __real_sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t);
ssize_t __wrap_sendto
(
int sockfd,
const void *buf,
size_t len,
int flags,
const struct sockaddr *dest_addr,
socklen_t addrlen
)
{
printf("my wrap sendto ...\n");
return __real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
When I use sendto in my own source code, the wrapper is in fact used ok but all 3rd party shared objects i linked against in my final g++ command that use sendto still use the system sendto i.e. not my wrapper. How can I get my sendto wrapper used throughout?
I have also tried an LD_PRELOAD approach with a sendto and dlsym(RTLD_NEXT) inside but that did not work either.
How can I figure out why the 3rd party library keeps on using the libc sendto directly?
When I use ldd to find all shared object dependencies of my compiled app and then objdump -T on each one of them grepping for sendto, I get UND (undefined) for all the 3rd party shared objects. The shared objects that do define it however is:
/lib64/libpthread.so.0
000000000000ed80 w DF .text 0000000000000064 GLIBC_2.2.5 sendto
/lib64/libc.so.6
00000000000e98d0 w DF .text 0000000000000064 GLIBC_2.2.5 sendto
I see in glibc sendto.c on git the following:
weak_alias (__libc_sendto, sendto)
weak_alias (__libc_sendto, __sendto)
The --wrap sendto option does not define the sendto symbol in your binary. Instead, it replaces references to this symbols with __wrap_sendto and leaves sendto undefined.
In other words, your executable does not provide sendto, so the run-time symbol resolution picks the one from glibc.
To fix this you need to define sendto in your executable. Try dlsym once again, but this time without LD_PRELOAD/shim library:
ssize_t sendto
(
int sockfd,
const void *buf,
size_t len,
int flags,
const struct sockaddr *dest_addr,
socklen_t addrlen
)
{
ssize_t (*libc_sendto)(int, const void *, size_t, int, const struct sockaddr *, socklen_t)
= dlsym(RTLD_NEXT, "sendto");
printf("my wrap sendto ...\n");
return libc_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
If third-party libraries keep finding wrong sendto after this, then I see only one (not particularly likely) possibility. Shared libraries are linked with -Bsymbolic/-Bsymbolic-functions and provide their own sendto.
Also, since you've tagged this question as g++, make sure that your symbol names don't get mangled - use extern "C".
I have eventually managed to figure out what was going on here. Even though the strace states sendto is being called:
[pid 17956] sendto(4, "abc"..., 2052, 0, NULL, 0) = 2052
what was in fact happening was send(...) was being called (probably possible because 0, null, 0 last three parameters). The moment I made an interceptor for send(...) it worked.

CppUTest example doesn't work

I just installed CppUTest on my MAC using brew as indicated by the guide.
It failed when I tried to build the example cpp.
TEST_GROUP(FirstTestGroup)
{
};
TEST(FirstTestGroup, FirstTest)
{
FAIL("Fail me!");
}
I guess it is because the header file which define those macros are not included. So I add include as below:
#include "CppUTest/TestHarness.h"
#include "CppUTest/TestOutput.h"
TEST_GROUP(FirstTestGroup)
{
};
TEST(FirstTestGroup, FirstTest)
{
FAIL("Fail me!");
}
Now I get bunch of errors.
Undefined symbols for architecture x86_64: "UtestShell::assertTrue(bool, char const*, char const*, char const*, int)", referenced from: vtable for TEST_FirstTestGroup_FirstTest_TestShellin ccNDwnbv.o
The error you are getting is a linker error and it suggests that you are not linking the CppUTest library. It is hard to actually say what is wrong because your question is missing the Makefiles. Could you explain how you have compiled the example?

Visual Studio, MSBuild: First build after a clean fails, following builds succeed

There's obviously something wrong with my build, but I can't figure it out. I narrowed this down to one of my projects: first build after clean fails, all following builds succeed.
I get linking errors which say that some symbols are already defined:
>------ Build started: Project: Problem, Configuration: Debug Win32 ------
> Blah blah blah...
23> Creating library D:\SVN.DRA.WorkingCopy\Debug\Problem.lib and object D:\SVN.DRA.WorkingCopy\Debug\Problem.exp
23>ProblemDependency1.lib(PD1.obj) : error LNK2005: "public: unsigned short __thiscall PD2Class::getFoo(void)const " (?getFoo#PD2Class##QBEGXZ) already defined in ProblemDependecy2.lib(ProblemDependency2.dll)
23>ProblemDependency1.lib(PD1.obj) : error LNK2005: "public: void __thiscall PD2Class2::`default constructor closure'(void)" (??_FPD2Class2#Image#DRA##QAEXXZ) already defined in ProblemDependency2.lib(ProblemDependency2.dll)
23>D:\SVN.DRA.WorkingCopy\Debug\Problem.dll : fatal error LNK1169: one or more multiply defined symbols found
Problem is a C++/CLI project, built with the /clr switch, which references the unmanaged C++ projects ProblemDependency1, a static lib, and ProblemDependency2, a dll.
ProblemDependency1 references ProblemDependency2.
getFoo() is declared as inline and defined outside of the class declaration, in the .h
PD2Class2 doesn't have an explicitly defined default constructor, but it has a constructor which has all default arguments, so you could say it includes the default constructor as a special case
The .h's where these are defined have #pragma once as their first line.
Any hint on troubleshooting this? I can post more info if needed
Update: I solved the first error thanks to Anders Abel's suggestion, but I still can't solve the second one (the one about the default constructor)
Update: If I compile using MSBuild outside Visual Studio, it fails always, with the same error
Edit: Here's some code. First, a bit of PD2Class2's declaration. PD2Class2's real name is CImage (feeling lazy to anonymize), CImage.h:
#pragma once
#pragma warning( disable: 4251 ) //TODO: Disable and solve
#include "ImageProperties.h"
#include "../CommonCppLibrary/CriticalSection.h"
#include <windows.h>
#include <stdexcept>
#include <string>
class CSharedMemory;
class EmptyImageException;
struct IShape;
struct SImageStatics {
unsigned short low3Percentile;
unsigned short high97Percentile;
unsigned short medianPixelValue;
unsigned short meanPixelValue;
unsigned short minPixelValue;
unsigned short maxPixelValue;
};
namespace DRA{
namespace Image{
class __declspec(dllexport) CImage {
friend class CImageLock;
//Attributes
int m_iPitch;
protected:
mutable CImageProperties m_cProperties;
CSharedMemory * m_pSharedMemmory;
mutable DRA::CommonCpp::CCriticalSection m_csData;
static const float PIXEL_FREQUENCY_COVERAGE;
static const float PIXEL_CUTOFF_PERCENTAGE;
static const int MINIMUM_PIXEL_FREQUENCY; //Pixels with a frequency lower than this are ignored
static const int MINIMUM_WINDOW_WIDTH_FOR_16_BITS;
//Methods
//Some private methods
public:
CImage( DWORD dwWidth = 0, DWORD dwHeight = 0, ULONG uBytesPerPixel = 0,
bool isSigned = false, EPhotometricInterpretation ePI = PI_UNKNOWN,
UINT bitsStored = 0, float pw = -1.0f, float ph = -1.0f, BYTE * pData = NULL );
CImage( const CImageProperties& cProperties, int iPitch = 0 );
CImage( const CImage& rImage );
virtual ~CImage();
virtual CImage& operator=( const CImage& );
bool operator==( const CImage& rImage );
//Alter State
//More methods
//Query State
//More methods
};
}
}
Next, the constructor's definition, from CImage.cpp:
CImage::CImage( DWORD dwWidth, DWORD dwHeight, ULONG uBytesPerPixel, bool isSigned,
EPhotometricInterpretation ePI, UINT bitsStored, float pw, float ph,
BYTE * pData ) :
m_iPitch( dwWidth * uBytesPerPixel ),
m_cProperties( dwWidth, dwHeight, uBytesPerPixel, bitsStored, ePI, isSigned, pw, ph ),
m_pSharedMemmory( NULL ),
m_csData(){
m_pSharedMemmory = new CSharedMemory( pData ? pData : new BYTE[getSize()] );
}
Is getFoo() marked as __declspec(dllexport)? If it is an inline function, it is instantiated/used from wherever it is called through the included header. It shouldn't be part of the functions that the dll exports and it should not have a dllexport directive.
__declspec(dllexport) might be handled through a macro that is expanded to dllexport or dllimport depending on if it is the dll or code using the dll that is compiled. If there is any macro in the function declaration you might have to dig into it to find if there is an export directive.
Update
I think that if the header file is used both when the dll is built and when the dll is used, it is incorrect to have __declspec(dllexport) in the header file. Instead use a macro system:
#ifdef PROBLEMDEPENDENCY2
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT CImage
{
//...
}
Then define the PROBLEMDEPENDENCY2 preprocessor symbol when building the dll, but not when using it. The problem with hardcoding __declspec(dllexport) in the header file is that the compiler will try to export the class both from ProblemDependency2 (which is correct) and from ProblemDependency1 (which is incorrect).
Just something I've run into recently to check:
Are you building on a network volume? I had been having problems with not being able to debug my applications because the .pdb file was not "there" after the build and before the debug launch due to latency in the SAN that I was working on as a build directory.
Once I moved the project build to a local volume, everything was fine.
Don't know if that's what's happening to you or not, but something I'd look into.
I dont' have much c++ experience, but problems like this in other .NET languages, often result from having a DLL reference to another project in the same solution (to the DLL in the "obj" or "bin" folder of the other project, instead of a project reference. This stops Visual Studio from being able to figure out the build order, and, hence, the first time after a "clean", you will not have the DLL you are depending on. On the second build, this DLL will already have been built, and the build will succeed.

Resources