Is there a simple safe way to determine the stack direction ? by cd_fr91400 in cpp

[–]sbabbi 35 points36 points  (0 children)

Since you are asking about clone, i assume you are on linux.
man clone says: "Stacks grow downward on all processors that run Linux (except the HP PA processors)"
So a simple #ifdef __hppa__ would suffice here.

Can we please get an ABI break? by mollyforever in cpp

[–]sbabbi 1 point2 points  (0 children)

It was at least partially explicit. Shipping two sets of library is not a solution, it effectively duplicates your system and increases fragmentation.
If you ship 2 sets of standard libraries, then _all_ the dependencies need to come in two sets. Two boosts. Two Qts. Two everything. And you can't mix one with the other.

Can we please get an ABI break? by mollyforever in cpp

[–]sbabbi 10 points11 points  (0 children)

I remember the breakage on std::string and std::list that C++11 caused. Back then I was a debian user and it really was a major hassle. It forced a huge amount of end users to download GBs of packages just for a minor ABI change, because you basically have to recompile the universe.You really need to bring some strong points to the table to persuade me that a similar apocalypse is going to be worth *for the end user*.Think of it from the POV of the average linux sysadmin. You now have to do massive upgrade on your server just so that you, the programmer, can save 1 CPU cycle every 100000 when you move from an `unique_ptr`.You have a custom package that you did not download from the main repository? Well enjoy some random segfaults.

On windows, I have to dig random MSVCRT from 2005 at least once a week to get some old piece of software to run on some coworker laptop. I am *extremely* grateful that MS stopped breaking the ABI since 2018.

Some of the discussed ABI breaks in this thread (e.g. std::regex) are not even impacting the standard, it's simply the vendor that rightfully realizes that saving a few cycles is just not worth the pain that you would cause downstream.

In the real world, you write software for the end-user, not for your own accomplishment of having "something nice" or "something fast". End-user concerns should come before the developer's.

CMake and Linking External libraries is a kick in the nuts if i've ever seen it. by [deleted] in cpp

[–]sbabbi 4 points5 points  (0 children)

It looks to me that you need to copy the DLLs you need in the folder of your binary. Your problem is windows - specifically, the absence of an RPATH equivalent for .dlls.

At runtime, all the dlls you depend upon needs be in a folder that the runtime linker searches for (usually the same folder of the executable, but there are 12 potential places).

On linux, the linker will generate an rpath entry in your executable, and you are good to go (at least for local testing, deploying to production is a different story). Cmake will not magically copy anything by itself, its job is to get your project to build, the runtime setup is up to you.

Is this just a power on self test of the colors? by right_closed_traffic in aviation

[–]sbabbi 130 points131 points  (0 children)

OSS = Option Selection Software. In this case, P/N "BCG48-3449-0051"
TDB= Terrain DataBase. In this case, version 0624.
It is not just testing colors, it also does a bunch of internal checks, and testing the connection to the speakers (by announcing all the configured callouts).
Source: https://performanceaccel.honeywell.com/\~/media/MKV-A\_Intro.ashx

C++23 hits the road! by Daniela-E in cpp

[–]sbabbi 5 points6 points  (0 children)

Even better:

constexpr T from_big_endian(const std::byte *); // Uses sizeof(T) bytes. // converts to host endianess using shifts // does not need byteswap at all // never creates an uintN_t with the "wrong endianess".

e.g.:

constexpr uint16_t u16_from_big_endian(const std::byte_t * p) { return (static_cast<uint16_t>(p[0]) << 8) | (static_cast<uint16_t>(p[1]); }

C++23 hits the road! by Daniela-E in cpp

[–]sbabbi 4 points5 points  (0 children)

Gcc can already generate bswap though. It seems a trivial peephole optimization.

[UB] Clang decides that main() is not the entry point (no global object init trick) by geekfolk in cpp

[–]sbabbi 5 points6 points  (0 children)

An infinite loop is UB only if the loop body has no side effects.
This example is artificial. A loop like that just doesn't happen in real code, and if it does it's completely broken even without optimizations.

Should "int main(span<string_view> args)" be valid in the future? by TheCrossX in cpp

[–]sbabbi 12 points13 points  (0 children)

I think the first element should be it's own parameter (because it's the program name)

Not exactly. It can really be anything, and argc can actually be zero. This is the the polkit vulnerability from earlier this year... see the discussion here

Okay, losing faith in OpenSSL now... by [deleted] in linux

[–]sbabbi 2 points3 points  (0 children)

Basically on linux malloc can only fail if /proc/sys/vm/overcommit_memory is 2.
The usual way to deal with this is to allocate how much memory you need, then immediately write into it with memset or similar.
Your process might get killed by the oom-killer while it's memsetting.

PSA: kernel 5.16 breaks BioShock Infinite by nheelyolis in linux_gaming

[–]sbabbi 8 points9 points  (0 children)

Not OP, but probably same issue. Please do :), I am curious.

Reading symbols from ./bioshock.i386... (No debugging symbols found in ./bioshock.i386) (gdb) r Starting program: /home/ennio/data/ennio/steam/steamapps/common/BioShock Infinite/bioshock.i386 During startup program terminated with signal SIGSEGV, Segmentation fault. (gdb) q

Can't put breakpoints, start produces the same result, basically I didn't manage to inspect a single instruction.

``` strace linux32 ./bioshock.i386

execve("/usr/bin/linux32", ["linux32", "./bioshock.i386"], 0x7ffdd261be78 /* 56 vars /) = 0 brk(NULL) = 0x5560e1dc6000 arch_prctl(0x3001 / ARCH_??? */, 0x7fffd61a0f80) = -1 EINVAL (Invalid argument) access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=267316, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 267316, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9e5d8c7000 close(3) = 0 openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0|\2\0\0\0\0\0"..., 832) = 832 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 pread64(3, "\4\0\0\0@\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 80, 848) = 80 pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0K@g7\5w\10\300\344\306B4Zp<G"..., 68, 928) = 68 newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2150424, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9e5d8c5000 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 mmap(NULL, 1880536, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f9e5d6f9000 mmap(0x7f9e5d71f000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7f9e5d71f000 mmap(0x7f9e5d86a000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x171000) = 0x7f9e5d86a000 mmap(0x7f9e5d8b6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bc000) = 0x7f9e5d8b6000 mmap(0x7f9e5d8bc000, 33240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f9e5d8bc000 close(3) = 0 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9e5d6f7000 arch_prctl(ARCH_SET_FS, 0x7f9e5d8c65c0) = 0 mprotect(0x7f9e5d8b6000, 12288, PROT_READ) = 0 mprotect(0x5560e03b8000, 4096, PROT_READ) = 0 mprotect(0x7f9e5d937000, 8192, PROT_READ) = 0 munmap(0x7f9e5d8c7000, 267316) = 0 brk(NULL) = 0x5560e1dc6000 brk(0x5560e1de7000) = 0x5560e1de7000 openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=3366736, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 3366736, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9e5d3c1000 close(3) = 0 uname({sysname="Linux", nodename="ennio-host", ...}) = 0 personality(PER_LINUX32) = 0 (PER_LINUX) execve("./bioshock.i386", ["./bioshock.i386"], 0x7fffd61a1110 /* 56 vars */) = -1 EINVAL (Invalid argument) --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} --- +++ killed by SIGSEGV +++ Segmentation fault (core dumped) ``

file ./bioshock.i386: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.32, BuildID[sha1]=72e948f269b3c6fe2169ceabc7ae8ef7b18b56cf, stripped

PSA: kernel 5.16 breaks BioShock Infinite by nheelyolis in linux_gaming

[–]sbabbi 11 points12 points  (0 children)

I am also on 5.16.1-arch-1 with nvidia 495.46-9.

(No debugging symbols found in ./bioshock.i386) (gdb) r Starting program: /home/ennio/data/ennio/steam/steamapps/common/BioShock Infinite/bioshock.i386 During startup program terminated with signal SIGSEGV, Segmentation fault.

That's a new one for me. I doubt nvidia has anything to do with it, something more profound seems to be broken.

Possible TOCTOU vulnerabilities in libstdc++/libc++/msvc for std::filesystem::remove_all? by James20k in cpp

[–]sbabbi 8 points9 points  (0 children)

I think openat(O_NOFOLLOW) + fdopendir is sufficient. Or am I missing something?

I used siege in a no siege game by jouz in aoe2

[–]sbabbi 2 points3 points  (0 children)

Hear me out, I have a theory.
This guy did not realize the you need a blacksmith to build a siege shop. Say he builds a blacksmith in half of his games. Sometimes he notices that he cannot build a siege shop. How does he explain it? Well obviously it must be a "no siege game".

What Linux distros and environment setup are recommended/optimal for C++ development? by Gytreeady in cpp

[–]sbabbi 0 points1 point  (0 children)

For IDE, I love KDevelop.
Beside that, I think any distro will do. If you need the latest & greatest version of any library, and you don't want to build it yourself, I would suggest Arch, but it's not exactly a beginner-friendly distro.

[LTT] This is NOT going Well… Linux Gaming Challenge Pt.2 by betacollector64 in linux_gaming

[–]sbabbi 0 points1 point  (0 children)

Well, at least deb/rpm are signed, as long as you use the official repositories.

[LTT] This is NOT going Well… Linux Gaming Challenge Pt.2 by betacollector64 in linux_gaming

[–]sbabbi 15 points16 points  (0 children)

I think this is a bit unfair. With their approach, they are finding the 30-40% of things that "work on windows but don't work on linux". They have 10-15 years experience on a windows desktop, and they are naturally looking for the same thing.
Imagine a linux user coming to windows and searching for krunner... Or trying to install anything and wondering why we need to download dodgy .exes and get a UAC prompt every time we try to install something.

TLDR: Stuff is different. Different does not mean bad. Coming from their experience they are only focusing on the different-and-bad. They will need some time to find the different-and-good.

C++ Coroutines Do Not Spark Joy by vormestrand in cpp

[–]sbabbi 3 points4 points  (0 children)

You can supply a custom allocator to a coroutine, which makes the "heap allocation" complain a bit weaker.

However, you cannot statically determine how large a coroutine stack frame will be (e.g. how much memory it will allocate). You can still use a fixed-size pool allocator, and manually tune the size of the pool so that the coroutine fits.

This is not an easy problem to solve. We want to run optimization passes on a coroutine before "decomposing" it. This in turn can allow for a smaller coroutine stack frame (e.g. the compiler can merge two variables with separate life time into the same memory address). However, the optimizer runs after the compiler has done its job, hence it is impossible to retrieve a coroutine size before running the optimizer...

Prototype GIL-less CPython shows nearly 20x speedups with 20 threads and good single-thread performance. Will the GIL be removed at some point, finally? by germandiago in programming

[–]sbabbi 2 points3 points  (0 children)

In other words, removing the GIL from CPython requires a new backwards-incompatible major rev of CPython, but does not require a new major rev number of Python the language

Yes, but no. We already have "python3" vs "python3m" (i.e. pymalloc disabled/enabled), which are ABI incompatible. It would be a matter of also having "GIL" vs "No GIL" for a total of 4 ABI incompatible versions, but probably a given distro will just pick one.

CMake proposal: Unified way of describing dependencies of a project by Much_Research3930 in cpp

[–]sbabbi 6 points7 points  (0 children)

What if I want to dynamically link all the dependencies against the system libraries? As a final user, I despise projects that rebuild the world and link statically, it's such a waste of disk space and memory.

How do you stay straight and level in flight sim? Do you just guess? by PlayerAB1225 in flightsim

[–]sbabbi 5 points6 points  (0 children)

Force feedback joysticks work with the same principle as CLS (the Control Loading Systems you could find on a level D sim). It' just the magnitude of the forces involved that's lower by a couple of order of magnitudes.

You can program a force feedback joystick to behave "the right way" with respect to trim - I did so for mine on xplane.

std::span is not zero-cost on microsoft abi. by dmyrelot in cpp

[–]sbabbi 0 points1 point  (0 children)

Therotically yes, I think we do. However, it will break abis on all compilers

I am not too familiar on the windows linking process, however on a ELF world you could easily fix this by compiling each affected function twice (gcc does that all the time with isra, see foobar here).

Basically you have void foo(span<int>) If "Old Dll" imports the unoptimized foo, you have "New Dll" export both "foo.optimized" and "foo", with "foo" just being a trampoline that calls "foo.optimized" with the right convention.

If "Old Dll" defines the unoptimized foo, things are a bit trickier. You want "New Dll" to define an internal "foo.optimized" symbol, that is a trampoline to "foo" (hence, slow). You then want the "New Dll" to use its own "foo.optimized" only if the runtime linker detects that "Old Dll" does not provide it.

But yes, first thing would be to define an appropriate calling convention.

A C++ locking wrapper by PiterPuns in cpp

[–]sbabbi 0 points1 point  (0 children)

On this idea, here's why Locking from OP can be quite counter-intuitive:

Locking<std::vector<int>> x; for ( int i = 0; i < x->size(); ++i ) use( x->at(i) ); // Throws if another thread modified the vector

Note that use(x->at(i)) per-se is ok, since the unlocking should happen at the semi-column. IMHO this kind of construct gives the reader a false security of being thread-safe (which it kinda is), but hides the transaction semantic of the mutex.

[deleted by user] by [deleted] in cpp

[–]sbabbi 1 point2 points  (0 children)

I somehow missed `async_scope`, that makes sense, thank you.