I need a compile time check for what version of glibc will be used.
The only compile time checks (ie #defines) I can find return the glibc date (__GLIBCXX__) and correspondence between the date and version seems iffy. How do you check at compile time for the version of glibc that will be used?
My code will compile and run on several systems, including a very old one. In particular I am interested in using malloc_info (see http://man7.org/linux/man-pages/man3/malloc_info.3.html). This was added to glibc in version 2.10. The program will be used on the same (or an identical system) it was built on.
I think what you're looking for is __GLIBC__ and __GLIBC_MINOR__, which represent an int of the major and minor version numbers of the GNU C Library. Have a look at this(archive link) for more details.
So if __GLIBC__ is greater than 2, or __GLIBC__ is equal to 2 and __GLIBC_MINOR__ is greater than or equal to 10, then malloc_info() should work.
Related
I am programming an application in Kotlin that converts radians to degrees and vise-versa. I was testing it with JUnit and received this error.
// The code I ran
assertEquals(60.0, radians.toDegrees())
// The stacktrace
org.opentest4j.AssertionFailedError:
Expected :60.0
Actual :59.99999999999999
There is nothing I can do about this, as the program was dividing by PI and then multiplying by PI later on. I was wondering if there was a way I could run a comparison that would count this as a success because the values are close enough. In Python, you can use assertAlmostEqual() with a couple of parameters. What is the equivalent of doing this with JUnit.
I am using JDK 11, Java 8, Kotlin 1.3(whatever the latest version is)
In JUnit 4 and JUnit 5 you can specify a delta in the method when comparing doubles, specifying how much variance you are willing to tolerate.
assertEquals(60.0, myValue, 0.005);
There's also the Hamcrest IsCloseTo matcher, which sounds more like what you're used to.
The preview version of Kotlin includes M, like 1.4-M2.
What does this mean?
https://github.com/JetBrains/kotlin/pulls?q=is%3Aclosed+milestone%3A1.4
Stands for Milestone 2. <major>.<minor> <qualifier>
It is a qualifier, which means that it is a preview release before the final 1.4 release.
https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN400
https://blog.soebes.de/blog/2017/02/04/apache-maven-how-version-comparison-works/
I'm using docplex to build up a mixed integer program which is then solved via cplex. However, upon trying to solve the MIP I receive the following error:
CPLEX> read plan.lp
CPLEX Error 1434: Line 184224: Couldn't convert '1<->' to a number.
No file read.
Looking at the lp file, the following line can be seen to be the problem:
1 <->
M13790
+ M13791
>= 1
And the line which creates the constraint is:
ilp.add_if_then(
ilp.sum([x.select_var for x in self.allX]) >= 1,
self.select_var == 1,
)
Where ilp is the docplex.mp.model object and each select_var is a binary decision variable. I'm really unsure of why this may be happening, and I'd appreciate any help with it!
Logical constraints (such as add_if_then) require a CPLEX 12.8 runtime to solve. If you run DOcplex with an older version of CPLEX in you PYTHONPATH, then an error should be raised.
If CPLEX is not found in PYTHONPATH, then DOcplex has no way to guess which version you'll be using (you might want to submit a Python job to DOcplexcloud, in which case your model will be solved with a CPLEX 12.8 runtime)
The generated LP file contains logical equivalence syntax (<->) which may not be read by older versions of CPLEX. Again, the best way to solve such LPs is to use a CPLEX 12.8 either by upgrading your local library or going to the cloud.
I have a simple hello world objective-c lib:
hello.m:
#import <Foundation/Foundation.h>
#import "hello.h"
void sayHello()
{
#ifdef FRENCH
NSString *helloWorld = #"Hello World!\n";
#else
NSString *helloWorld = #"Bonjour Monde!\n";
#endif
NSFileHandle *stdout = [NSFileHandle fileHandleWithStandardOutput];
NSData *strData = [helloWorld dataUsingEncoding: NSASCIIStringEncoding];
[stdout writeData: strData];
}
the hello.h file looks like this:
int main (int argc, const char * argv[]);
int sum(int a, int b);
void sayHello();
This compiles just fine on osx and linux using clang and gcc.
Now my question:
When running a clean compile against hello.m multiple times with clang on ubuntu the generated hello.o can differ. This seems not related to a timestamp, because even after a second or more, the generated .o file can have the same checksum. From my naive point of view, this seems like a complete random/unpredicatable behaviour.
I ran the compilation with the -Sto inspect the generated assembler code. The assembler code also differs (as expected). The diff file of comparing the assembler code can be found here: http://pastebin.com/uY1LERGX
From a first look it just looks like the sorting is different in the assembler code.
This does not happen when compiling it with gcc.
Is there a way to tell clang to generate exactly the same .o file like gcc does?
clang --version:
Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)
The feature when compiler always produce the same code is called Reproducible Builds or deterministic compilation.
One of possible sources of compiler's output instability is ASLR (Address space layout randomization). Sometimes compiler, or some libraries used by it, may read object address and use them, for example as keys of hashes or maps; or when sorting objects according to their addresses. When compiler is iterating over the hash, it will read objects in the order that depends on addresses of objects, and ASLR will place objects in different orders. The effect of such may looks like your reordered symbols (.quads in your diffs)
You can disable Linux ASLR globally with echo 0 | sudo tee /proc/sys/kernel/randomize_va_space. Local way of disabling ASLR in Linux is
setarch `uname -m` -R /bin/bash`
man page of setarch says: -R, "--addr-no-randomize" Disables randomization of the virtual address space (turns on ADDR_NO_RANDOMIZE).
For OS X 10.6 there is DYLD_NO_PIE environment variable (check man dyld, possible usage in bash export DYLD_NO_PIE=1); in 10.7 and newer there is --no_pie build flag to be used in building the LLVM itself or by setting _POSIX_SPAWN_DISABLE_ASLR which should be used in posix_spawnattr_setflags before starting the llvm; or by using in 10.7+ the script http://src.chromium.org/viewvc/chrome/trunk/src/build/mac/change_mach_o_flags.py with --no-pie option to clear PIE flag from llvm binaries (thanks to asan people).
There were some errors in clang and llvm which prevents/prevented them to be completely deterministic, for example:
[cfe-dev] clang: not deterministic anymore? - Nov 3 2009, indeterminism was detected on code from LLVM bug 5355. Author says that indeterminism was present only with -g option enabled
[LLVMdev] Deterministic code generation and llvm::Iterators (2010)
[llvm-commits] Fix some TableGen non-deterministic behavior. (Sep 2012)
r196520 - Fix non-deterministic behavior. - SLPVectorizer was fixed into deterministic only at Dec 5, 2013 (replaced SmallSet with VectorSet)
190793 - TableGen: give asm match classes deterministic order. "TableGen was sorting the entries in some of its internal data structures by pointer." - Sep 16, 2013
LLVM bug 14901 is the case when order of compiler warnings was Non-deterministic (Jan 2013).
The patch from 14901 contains comments about non-deterministic iterating over llvm::DenseMap:
- typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap;
+ typedef std::pair<UsesVec*, bool> MappedType;
+ // Prefer using MapVector to DenseMap, so that iteration order will be
+ // the same as insertion order. This is needed to obtain a deterministic
+ // order of diagnostics when calling flushDiagnostics().
+ typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
...
- // FIXME: This iteration order, and thus the resulting diagnostic order,
- // is nondeterministic.
Documentation of LLVM says that there are non-deterministic and deterministic variants of several internal containers, like Map vs MapVector: trunk/docs/ProgrammersManual.rst:
1164 The difference between SetVector and other sets is that the order of iteration
1165 is guaranteed to match the order of insertion into the SetVector. This property
1166 is really important for things like sets of pointers. Because pointer values
1167 are non-deterministic (e.g. vary across runs of the program on different
1168 machines), iterating over the pointers in the set will not be in a well-defined
1169 order.
1170
1171 The drawback of SetVector is that it requires twice as much space as a normal
1172 set and has the sum of constant factors from the set-like container and the
1173 sequential container that it uses. Use it **only** if you need to iterate over
1174 the elements in a deterministic order.
...
1277 StringMap iteratation order, however, is not guaranteed to be deterministic, so
1278 any uses which require that should instead use a std::map.
...
1364 ``MapVector<KeyT,ValueT>`` provides a subset of the DenseMap interface. The
1365 main difference is that the iteration order is guaranteed to be the insertion
1366 order, making it an easy (but somewhat expensive) solution for non-deterministic
1367 iteration over maps of pointers.
It is possible that some authors of LLVM thought that in their code there was no need to save determinism in iteration order. For example, there are comments in ARMTargetStreamer about usage of MapVector for ConstantPools (ARMTargetStreamer.cpp - class AssemblerConstantPools). But how can we sure that all usages of non-deterministic containers like DenseMap will not affect output of compiler? There are tens loops iterating over DenseMap: "DenseMap.*const_iterator" regex in codesearch.debian.net
Your version of LLVM and clang (3.0, from 2011-11-30) is clearly too old to have all determinism enhances from 2012 and 2013 years (some are listed in my answer). You should update your LLVM and Clang, then recheck your program for deterministic compilation, then locate non-determinism in shorter and easier to reproduce examples (e.g. save bc - bitcode - from middle stages), then you can post a bug in LLVM bugzilla.
Try the -S option for clang and gcc during compiling your source. This will generate a .s file in which you can see the assembler code this could give you an idea what the differences on a lower level. Maybe you will realise the output will be the same and your problem shifts from the compiler further down to the linker.
You should report this as a bug; a compiler certainly should be deterministic.
Your guess about the sort order is quite probably correct, in my experience. Most likely the compiler makes an arbitrary decision when two items compare equal (according to whatever measure is significant; they don't have to be actually the same), and that can vary depending on environmental factors, somehow. I've seen this before, in GCC, in which the same compiler compiled for different host OS produced different results; in that case it turned out that the Windows qsort function operated slightly differently to the Linux (glibc) implementation.
That said, it could be something else; compilers aren't supposed to make random decisions, but there plenty of opportunities for arbitrary decisions that might turn out to be unstable, somehow (address space randomization, perhaps?)
"foo": "~0.2.1"
"foo": ">= 0.2.1"
What's the difference?
>= means any version equal or bigger to the mentioned release. For example 42.42.42 would be fine with >= 0.2.1 requirement (no matter how incompatible it would be in practice). Also, it means that 0.2.1-beta is not fine, as beta was before final release.
~ means reasonably close to the specified version (as in, compatible). It takes the semantic versioning definition, so any major version jumps aren't considered to be compatible (higher than the last number in specified version). For example, 42.42.42 or 0.3.0 is not fine with ~0.2.1 requirement. However, 0.2.1-beta or 0.2.42 is allowed, as it's reasonably close to the final version.
Tilde means next significant release. In your case, it is equivalent to >= 2.0, < 3.0.
A simple rule-of-thumb way is that the ~ allows the last digit to go up. e.g. ~2.2 means 2.2 and any 2.x where x is 2 or above. ~2.1.3 on the is also any 2.1.x where x is 3 or above.
http://getcomposer.org/doc/01-basic-usage.md#package-versions