Error compiling a c++ database on windows with cmake - c++

For my Masters degree I need to work on a database called duckdb (its on git hub). Normally on Linux you can simply clone it and "make" it to install.
I tired the same on windows after installing CMake and Cygwin.
But halfway through compiling I get the error
'DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1445:96:
error: ISO C++
forbids comparison between pointer and integer [-fpermissive]
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }'
Since I doubt that the creators of duckdb did mess this up, I think there is a compiler error trying to compile a C file as C++ file, maybe.
My main problem is: how do I configure the make command on windows to stop it from producing this error?
I tried it both on a windows 7 and 10 system with gcc 5.1 and current cmake installed, and both produce this error.
Edit: Here is the full error text
[ 87%] Building CXX object test/sql/capi/CMakeFiles/test_sql_capi.dir/ub_test_sql_capi.cpp.obj
In file included from C:/duckdb/test/sql/capi/test_capi.cpp:1:0,
from test_capi.cpp:0:
C:/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp: In instantiation of 'bool >Catch::compareNotEqual(const LhsT&, RhsT&&) [with LhsT = void*; RhsT = const >long long int&]':
C:/DB/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1471:37: required from 'const >Catch::BinaryExpr Catch::ExprLhs::operator!=(const >RhsT&) [with RhsT = long long int; LhsT = void* const&]'
C:/DB/duckdb/test/sql/capi/test_capi.cpp:332:2: required from here
C:/DB/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1445:96: error: ISO C++ forbids comparison >between pointer and integer [-fpermissive]
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return >static_cast(lhs != rhs); }
I only edited out my user name in the path etc.

I don't know the library, so I can't give definite answer. I will be going by the code at https://github.com/cwida/duckdb.
According to the error message in the problematic code is in line 332 of test/sql/capi/test_capi.cpp, which is:
REQUIRE(stmt != NULL);
REQUIRE is a macro from the unit testing library Catch2 that does some magic to parse the expression given to it. The important part is that stmt != NULL will not actually be executed immediately, but only through function indirection.
stmt is declared as in line 324 as
duckdb_prepared_statement stmt = nullptr;
and duckdb_prepared_statement is a typedef in line 94 of src/include/duckdb.h:
typedef void *duckdb_prepared_statement;
Therefore the intention of the problematic line is to check whether stmt is still a nullptr after some intermediate operations.
Normally stmt != NULL would be fine for that. However because the Catch2 macro introduces intermediate function calls rather than evaluating this expression directly, implicit conversions that are specific to the literal are not applied.
In particular NULL is according to the standard either a prvalue of type std::nullptr_t or an integer literal with value 0. Which of these exactly (and which integer type) is implementation-defined.
Comparing integers and pointers is generally forbidden, however integer literals of value zero have a special exception allowing them to be implicitly converted to a null pointer of any pointer type. This is what would happen if stmt != NULL would be evaluated directly.
However due to the interjection of Catch2, NULL is first passed around and later compared through a variable to stmt, which makes the special zero literal rule not apply any more. Therefore a comparison of stmt against NULL through REQUIRE would fail if NULL is an integer literal in the current implementation.
Catch2 does consider this problem and there are overloads for compareNotEqual in third_party/catch/catch.hpp that take care of the case where NULL is a zero integer literal of type int or long, but for some reason the case of long long is not considered. I don't know whether this is a problem with Catch2 or whether it is only in the cloned version included in duckdb.
So, if the implementation uses a zero literal of type long long for NULL, then the error you observed will happen.
Really duckdb should use nullptr instead of NULL (as it does in the initialization), which does not have these problems and was added to the language because of exactly these problems.
I suppose you can simply try to fix this issue by replacing NULL with nullptr (maybe in other test cases as well).
However the problematic code is only in files which are themselves unit tests for the actual library code. So there should be some option to cmake or make that will disable building the unit tests, so that you can ignore this particular error, hoping that it doesn't occur anywhere in the actual library code as well.
If I was correct in my assessment, you might want consider filing a bug report for this with duckdb, assuming they do support your platform in the first place.

Rather than using Cygwin, it might be easier to use CMake combined with Visual Studio to compile the project. This is the way that the authors compile and test DuckDB on Windows themselves.
Using CMake, generate a set of Visual Studio Project files. Then open those project files in Visual Studio (we use Visual Studio Community 2019), and compile and run the test suite (unittest). Individual tests can be run by adding the test name as a command line parameter.

DuckDB doesn't seem to have a release version at this time. So don't assume it the creators didn't leave any errors in...
You can add compiler flag -fpermissive to ignore the error (e.g. make CXX="g++ -fpermissive").
But ignoring errors like this isn't always safe.
So I tried to fix the issue, and I was able to build a version on Windows. See https://github.com/cwida/duckdb/issues/361 for my solution.

Related

Why has assignment to a gr_complex variable (GNU Radio) stopped working for me?

In the block definition for my custom SDR transceiver hardware I use the following complex variable:
gr_complex complexSample;
In my code, which has worked successfully for two years before a recent upgrade to the latest gnuradio release, I use the following assignments:
complexSample.real() = realInt;
complexSample.imag()= imagInt;
However, when I try to compile now, I get the following error:
error: lvalue required as left operand of assignment
Frustratingly, if I remove the pair of parentheses, I get the following error:
error: invalid use of member function 'void
std::complex::imag(float)' (did you forget the '()'? )
The original version of gnuradio I have been using is 3.7.5-5, and the latest I have upgraded to is: 3.7.10.1-2.
Has something significant changed between these two releases which could explain this difference in behaviour?
If so, what is the solution?
Could this be something to do with 'Volk integration' (whatever that is...).
No, GNU Radio didn't change gr_complex. It's still but an alias for std::complex<float>.
What probably has changed is that you're now using a compiler set to C++14, and that makes std::complex<float>.real() return a const that you can't assign to. (I think that's what happens.)
You should either just construct the value like you mean to, i.e.
gr_complex foo(realpart, imagpart)
or use the setters
gr_complex foo;
foo.real(realpart);
foo.imag(imagpart);
As the error message shows, gr_complex is a typedef for std::complex<float>. That means the .real() and .imag() methods are getters, not setters.
That's not what you want anyway. You just want to assign the number, not its separate components: complexSample = gr_complex{realInt, imagInt}.

movefile() fails error 2 or 123

I'm updating a c++ routine to move files that was written in visual studio express 2008/2010. I'm now running VS Express 2012
Obviously there are changes to the compiler because string functions have to be upgraded to strcpy_s etc. No problem. This is a console app. I never extended my C++ knowledge past C++ to C# etc. as I need little more than to be able to write small utils to do things on the command line. Still I'm able to write somewhat complex utilities.
My issue is movefile() function always fails to move with either error 2 or 123. I'm working in C:\users\alan\downloads folder so I know I have permission. I know the file is there. Small snippet of code is:
char source=".\\test.txt"; // edited for clarity.
char dest=".\\test.txt1";
printf("\nMove\n %s\n to %s\n",source,dest); // just to see what is going on
MoveFile((LPCWSTR) source, (LPCWSTR) dest);
printf("Error %u\n",GetLastError());
output is :
Move
.\test.txt
to .\test.txt1
Error 2
All of my strings are simple char strings and I'm not exactly sure, even after reading, what LPCWSTR was type def'd for and if this is the culprit. So to get this to compile I simply typedef'd my strings. And it compiles. But still it won't move the files.
The code is more complex in developing the source & dest variables but I've reduce it to a simple "just append a 1 to the file name" situation to see if I can just simply rename it. I thought C:\xxx\yyy\zzz\test.txt was maybe wrong in some fashion but that idea fell though with the above test. I've done it with and without the .\ same issue. I'm running out of ideas other than making my own fileopen read/write binary function to replace movefile(). I'm really against that but if I have to I will.
EDIT: I pasted the printf from original code that used FullPathName, I've corrected the snippet.
The fact that you are casting your arguments to LPCWSTR suggests that you are compiling your program with UNICODE defined, which means you are calling MoveFileW and the compiler warned about an argument type mismatch.
Inserting a cast does not fix that. You are telling the compiler to stop complaining, but you haven't actually fixed the problem (the underlying data is still wrong).
Actual solutions:
Use WCHAR as MoveFileW expects (or TCHAR/LPTSTR and the _T macro).
Explicitly call MoveFileA
Compile without UNICODE defined.
Thanks Andrew Medico. I used MoveFileA and the program seems to work now.
I'm not sure I turned off unicode, but I did change one item in the properties.
I'll need to read up on the compiler about unicode/ansi settings. But for now the issue is fixed and I'm sure I've got the idea of what I need to do. "research"!!!!

UnicodeString compatibility issue

I am porting an older project from C++ Builder 2009 to XE5. In the old project, the compiler option for Unicode strings was set as "_TCHAR maps to: char". This worked fine in the old project.
When porting it, I set the same compiler option in XE5. But I still get compiler errors for code like this:
std::string str = String(some_component.Text).t_str();
This gives the following errors:
[bcc32 Warning] file.cpp(89): W8111 Accessing deprecated
entity 'UnicodeString::t_str() const'
[bcc32 Error] file.cpp(89): E2285 Could not find a match for
'operator string::=(wchar_t *)'
So apparently XE5 has decided that String::t_str() should give me a wchar_t* rather than a char*, even though I have set the compiler option as described above.
How do I solve this?
I am well-aware that C++ Builder has taken the step to use Unicode internally (even in the 2009 version), but this is an old project with 200k LOC. Updating it to Unicode would be a steep task with very low priority.
EDIT
I can get it to work by changing the code to
std::string str = AnsiString(some_component.Text).c_str();
But this means I have to change the code at numerous places. Is there a better way that doesn't involve rewriting code?
When UnicodeString::t_str() was first introduced in CB2009, it returned either a char* or wchar_t* depending on what TCHAR mapped to. In order to return a char*, it ALTERED the internal data of the UnicodeString to make it Ansi (thus breaking the contract that UnicodeString is a Unicode string). THIS WAS TEMPORARY for migration purposes while people were still re-writing their code to support Unicode. This breakage was acceptable because the RTL had special logic to handle Ansi-encoded UnicodeString (and Unicode-encoded AnsiString) values. However, this was dangerous code. After a few versions, when people had adequate time to migrate, this RTL logic was removed and UnicodeString::t_str() was locked in to wchar_t* only, to match UnicodeString::c_str(). DO NOT USE t_str() anymore! That is why it is marked as deprecated now. If you need to pass a UnicodeString to something that expects Ansi data, converting to an intermediate AnsiString is the correct and safe approach. That is just the way it is now.

Xcode: breakpoints in the C++ headers files seems to be ignored

I'm running in Xcode 4.3.3 an iOS project with some C++ classes.
When I run it in debug mode the breakpoints in the C++ headers files seem to be ignored. For example, the barcode on the third line of this code doesn't work:
class myClass : public Reader {
private:
static const int INTEGER_MATH_SHIFT = 8;
I'm expecting the code to break on the constant assignment, or am I wrong ?
Thanks
A breakpoint can only be set on executable code. The initialization of an object with static lifetime with a constant expression doesn't generate any executable code (and while you mention assignment, there's no assignment in the code you've posted). In fact, in the special case of a constant of integral type, it's likely that the object doesn't exist at all unless you take its address.
AFAIK, breakpoints can be set only on command lines not on assignments. If you set breakpoint on assignment in implementation file it will stop on next operator line

How do I prevent/suppress SIGFPE in C++?

I'm trying to convert a double to float as well as various integer types inside a dll, which is used as a Game Maker extension. I don't need a sensible result if the double doesn't fit the range of the target types, so I simply used a static_cast.
Everything works as intended when I call this code from my own test C++ application, but when it's called from Game Maker, range errors raise SIGFPE for some reason, which leads Game Maker to terminate my program with an error message.
I don't need sensible results for out-of-range conversions, but crashing is a no-no. I tried using llround instead of a cast, but it also raises the signal.
I also tried catching the signal myself by using signal(SIGFPE, SIG_IGN); right before the conversion, but it didn't change the behaviour at all. Maybe the ominous comment in the mingw signal.h has something to do with that: "SIGFPE doesn't seem to work?"
I checked the source code of a different dll used in a Game Maker extension, and the binary provided by the author performs simple cast conversions without a problem. When I compile the source myself however, the SIGFPE problem is present again. I am guessing that the author used a different compiler, but I'd prefer to stay with mingw if possible.
So, how do I either perform these conversions safely, or prevent the signal from being generated when I perform them with a simple cast? I'm using mingw-g++ 4.5.0 to compile at the moment.
Here's the function where the problem happens:
template<typename ValueType>
static double writeIntValue(double handle, double value) {
boost::shared_ptr<Writable> writable = handles.find<Writable>(handle);
if(writable) {
// Execution reaches this point
ValueType converted = static_cast<ValueType>(value);
// Execution doesn't reach this point if e.g. ValueType
// is short and value is 40000
writable->write(reinterpret_cast<uint8_t *>(&converted), sizeof(converted));
}
return 0;
}
The good solution is to perform the conversion correctly by ensuring that the source value is within the range of the target type before casting. So my code from the question could be corrected like this:
ValueType converted;
if(value >= std::numeric_limits<ValueType>::max()) {
converted = std::numeric_limits<ValueType>::max();
} else if(value <= std::numeric_limits<ValueType>::min()) {
converted = std::numeric_limits<ValueType>::min();
} else {
converted = static_cast<ValueType>(value);
}
Another option is to use numeric_cast from the Boost libraries, which throws an exception if the source value is out of range, so it has defined behaviour for all conversions.
The documentation of the Boost Numeric Conversion library contains some helpful information about how the standard defined certain conversions.
Thanks to rve for providing the correct suggestion in his answer, but unfortunately his example code is flawed, and I wanted to add some additional pointers that helped me.
Since you are using a DLL, are you sure the DLL is compiled in the same way as the program expects it? Maybe some 32/64 bit mismatch?
Also, SIGFPE can also be raised when there is an under/overflow when converting.
You can enable/disable the signal raised by this overflow by setting the mask using _FPU_SETCW (it's in fpu_control.h) My guess is that Game Maker enables this and your test program not.
I never tried this and I'm not sure mingw also has this but I hope this helps a little.
edit:
Why not making sure an overflow does not happen?
Something like:
if (value > std::numeric_limits<ValueType>::max())
{
value = std::numeric_limits<ValueType>::max();
}
else if (value < std::numeric_limits<ValueType>::min())
{
value = std::numeric_limits<ValueType>::min();
}
ValueType converted = value;
probably it's not related with conversion itself but with trying to access invalid memory (maybe stack corruptions or something like that). can you provide some code snippet?