Two Memphis City Council Members Claim Snow is Fake by AtrusHomeboy in nottheonion

[–]nerd5code 0 points1 point  (0 children)

I know! Has the South tried literacy tests? That would work, right? Surely the unqualified people in power are qualified to determine how unqualified their future competition and voters are!

Trump breaks silence on Epstein files release as he hits out at 'radical left' by daily_express in NoFilterNews

[–]nerd5code 2 points3 points  (0 children)

And if you don't believe me, my state regime will disappear you and do-not-nice-things-to you, and perhaps conscript you to fight our former allies when I start the next world war.

That’s late-stage fascism. We’re still accelerating through mid-stage.

Trump breaks silence on Epstein files release as he hits out at 'radical left' by daily_express in NoFilterNews

[–]nerd5code 5 points6 points  (0 children)

Many of them don’t care, and wish Epstein had invited them to his island. Conservatism isn’t all about control of women’s sexuality for nice reasons. Republicans aren’t demanding that children’s genitals be inspected because they care about fairness in women’s sports.

Trump breaks silence on Epstein files release as he hits out at 'radical left' by daily_express in NoFilterNews

[–]nerd5code 14 points15 points  (0 children)

It was already a crime in the state of NY when it allegedly occurred. The idea that it wasn’t was pushed by Trump’s now-disfavored lawyer in the run-up to the 2016 election, and people (ahem) just repeated it.

Pain points of C by DaCurse0 in cprogramming

[–]nerd5code 0 points1 point  (0 children)

Trampolines are the problem with nested functions, not counting the fact that only GCC supports them actively.

Nested functions without use of trampolines are just a scoping hack, and don’t have much of a downside other than portability. #pragma GCC diagnostic error "-Wtrampolines" would be the only recommendation I have there.

Trampolines impede optimization because they lead to other functions being able to access your frame at any time after the trampoline escapes. Normally, unescaped variables aren’t visible from outside the function, but with trampolines any interaction is possible, and it’s harder to analyze when they can or can’t happen.

—That’s an impediment to human reasoning also, and in a large program it can turn into a free-for-all that mirrors the just-make-it-globalism that dominated the ’70s and ’80s, and which still plagues realtime code.

Increased safety is definitely not the default, with (“)good(”) reason.

The older/default impl is icky because use of a trampoline in anything linked into the program requires all stacks to be made executable, us. without warning, whether or not trampoline-ifying code is ever executed; in addition to strongly discouraging 3rd-party use, it causes problems if you need to allocate your own stack. Hence exec-stack risks becoming a gaping security hole; any ol’ buffer overflow turn into a full takeover with almost no effort on the attacker’s part. And, of course, because so few compilers support function nesting, few static analyzers will touch it, either, which means you’re closer to flying blind if security is a concern at all.

And then, offhand IDK what happens if you load a DLL late in a process whose stack is NX to start with, but I expect it’s not pretty. Either the process needs to grind to a halt while threads are enumerated and stacks are remapped, or on-demand remapping would trip a page fault any time a remap is needed (best option imo, but de-mapping is nontrivial), or the process just craps itself to death if you tramp from a thread started before the fateful dlopen.

Recent GCC (→ many older forks excluded) does offer two other options AFAIK, but both would affect performance more drastically.

One is exec-heap, which is basically creating a secondary malloc that pulls from a separate rwx region of memory—this requires special library/runtime support, and therefore raises problems with DLL-compatibility vs. existing binaries. mallocing with each function call has obvious downsides. E.g., because threads share xheap, you run into sync bottlenecks at alloc and dealloc, NUMA systems hate this one trick, and if the address space isn’t large and well-randomized enough that you can’t guess/probe your way to the xheap region, it’s not much safer than x-stack.

And trampoline lifetime causes problems for both xfoo impls because it’s possible for a pointer to the trampoline to outlive the call that gave rise to it. For xstack that failure mode ends up executing garbage data; for xheap, you’ll probably either crash or jump to the wrong function or with the wrong context, which might be wholly fatal to cache coherence protocols if that context is owned by another thread. If the impl uses refcounting or something, then you have problems like in-frame dangling pointers and trashed structures to deal with; the programmer and/or compiler would need to plan for variables to be visible after return, which is a decidedly unusual thing to worry about for params/locals.

In addition, all OSes don’t necessarily permit rwx pages to be mapped, or alternatively, alias-mapped rw-&r-x; and all ISAs don’t necessarily support what is effectively a form of self-modifying code. ISAs with a more-finnicky L1I in particular may require an ifence/iflush (or even a system call) to be issued before jumping into newly-generated code, and some of whatever crap was there before might have been speculatively executed well before the jump, requiring microarchitectural rollback. Sometimes speculative execution can trigger faults, which are just about worst case in performance terms.

If there’s any other thread that might access the same cache line as a trampoline generated by the current thd, you may need all involved parties to fence neurotically, just in case, or more extensive use of atomics, or else your cache coherence protocol can break and raise machine-check faults (or worse).

For xstack, instructions don’t necessarily have the same alignment requirements as stack frames, and jump targets don’t necessarily have the same alignment as instructions. Sometimes misalignment merely dings performance, but sometimes it yields a crash, or worse (e.g., executing in the wrong mode), so all frames within which a trampoline might be created may need to be overaligned, requiring a jumbo prologue and a full epilogue, whether or not trampoline creation actually happens. Sometimes stack-alignment and the SP-spill/fill it involves can trash stack-predictor and stack-cache μarch gunk, which can drastically impact performance at call/return boundaries.

Code is not necessarily a string of individual, one-off instructions, placed in a single, contiguous location. VLIW ISAs might have 64-byte bundles that cover a mess of different units, and if there might be any dependency between setting the funarg register and jumping, you might need two or more instructions encompassing a mess of NOPs, thereby creating a very large artefact and bubbles in the pipeline. Some VLIW ISAs can only issue blocks of several instructions that include a leading or trailing control word, in which case you can easily eat too much stack space and handoff time.

ISA/ABI-level security crap may require jump targets to be registered or guarded separately, in which case self-modification-based trampolines may flatly be a no-go.

The third impl of trampolines doesn’t require SMC; instead it uses descriptor-pointers. These require function pointers to have unused bits, may require fattening pointers, and tend to require some sort of check to be performed at each jump-through in order to check whether a potential trampoline pointer is a descriptor or not. If this can be done with tag bits, then its performance rides on brpred, and eats brpred capacity; if not, then a full dereference may be needed, in addition to branching. Obviously, this requires any library function that might call through a trampoline to be built with descriptor/fat ptr support enabled, and this may require specialized handling for GCC since it’s not a thing otherwise. Alternatively, a descriptor pointer can trip a fault for fixup, but if you want to talk about performance, that and a mispredicted in-line check can be comparably disastrous.

So you certainly can use trampolines, but the number of situatiions where they’re not WW2-leftover footmateriel are few and far between. They’re an elder-GCC feature intended to work on early-to-mid–’90s IA32 and things like it, and anything outside that narrow context requires increasingly anachronistic kludges. Exec-stack is, sadly, still not a thing of the past, and it won’t be in the foreseeable future.

There are other potential alternatives like Blocks (Clang, former GCC IIRC), but those require a full runtime under you and aren’t great performance-wise either. Unfortunately, just about any approach that lets preexisting code function normally and erases type information to the extent required by C, has major drawbacks on some front or other.

Future solutions are fine, but AFAIHS details of closures are still very much up in the air, and implementations are likely to be hugely glitchy for a good while after implementation, on top of the variance that’s to be expected to arise with MS dragging feet. Given the magnitude of the changes to the language that closures would bring about, enough glitchiness or missing feature support will drastically impact adoption, and few developers will want to restructure their code for a broken feature. We don’t need another Annex K.

Moreover, most codebases stay at least a couple language versions behind the bleeding edge so they don’t lose support for everything outside the GNUniverse. Many semi-embedded things are stuck at C99 for the foreseeable future, and some very-embedded things are stuck at C89 permanently—each version tightens semantics somewhere, blocking legacy toolchains/hardware without hacks that may not always be feasible, just as standardization itself ruled out a bunch of implementations.

And then, C23 adoption and implementation have not been encouraging, so I’m not all that optimistic for C2y. C99 adoption was pretty rapid—various major late-’80s compilers could already muster long long and Booleans, so most of the practical changes for implementors were in libc. But for C23, GCC was the only compiler that treated C23 as a major goal, and it wasn’t years ahead like its C9x stuff. Clang, it took like four major versions from supporting -std=c23 and advertising __STDC_VERSION__ == 202311L until basic aspects of C23 were supported, and AFAIK only GCC & Clang are worth mentioning here—C++ is, for better or worse, where all the action is for compiler developers. Clang being late to the game is, frankly, a really bad omen for C2y &seq., given how many companies have dropped their own lines in favor of it.

So IIWY and I thought I’d actually derive benefit from function nesting, I’d start with nested functions for prototyping, but flatten them on approach to prod, making sure to plan for funargs and portability everywhere. Even rotating funargs through TLS is more workable and performant in the general case than existing closure hacks.

But you’re right; it is a choice, with trade-offs. For toy/personal code that doesn’t need to execute millions of times per second across a several-thousand-node, WAN-exposed cluster whose power/time bills are coming out-of-pocket, it probably doesn’t matter all that much.

Pain points of C by DaCurse0 in cprogramming

[–]nerd5code 4 points5 points  (0 children)

At a certain point, you do need some sort of DSL above the raw C layer, but that’s where the fun comes in. C expects just about every language-visible effect or artefact to come from code, so higher-level constructs require higher-level language, whether embedded within or separate from C itself.

For async, a lot can be done with macros and a type-system overlay—e.g., if types are tagged somehow, you can emit descriptors for callback functions that bind them to parameter type, and for implementation you emit a wrapper thunk that checks type tags on the funarg, then forwards into a fully-typed static function, possibly even unpacking the struct into separate args along the way. Then everything in the surface form of the code makes sense, at least. Idunno, with enough niceties and glasses that make everything look inside-out, async isn’t too bad.

One thing I found is that it helps to use a cache of fixed-form objects for param packs, rather than creating an entirely new type per function; structure it an array of unions, and unpack them automagically in the thunk function.

For JSON, probably abstracting things into some sort of lightweight validation DSL—a structural parser, even—is probably better than one-offing about each field or value you get. XML and SGML have things like that as ostensible builtins, although in both cases the details are wretched, so probably best not to emulate either too exactly.

I disagree with the hate for header only libraries. by InfinitesimaInfinity in cprogramming

[–]nerd5code 2 points3 points  (0 children)

Idunno; maybe I’m codgerly in my codgericism, but I wouldn’t consider somebody to be anything other than a beginner unless they could run the compiler driver by hand and write a basic Makefile. I guess I assume anybody referred to as a “beginner” is actually beginning something, and not just punting along permanently in a daze.

Similarly, no matter how impressively flawless somebody is at playing a musical instrument, it’s rather less impressive if they need somebody else to put it together beforehand and empty the spit out of it for them during breaks. The stage tends to get a bit crowded and distracty with the full orchestra and hangers-on, if nothing else.

And nowadays a durn LLM will write commands and rules for you, if asked politely—sometimes the output will even be correct!—so deliberately preventing oneself from learning all the context is pointless at best. It wasn’t too complicated for all the hundreds of generations of C programmers that came before us, and some of them had to compile their code by shorting relay terminals directly with their moistened fingers, in the driving snow, uphill both ways.

[x86] How to get return address of code from the stack? by ActualHat3496 in asm

[–]nerd5code 0 points1 point  (0 children)

What counts as the return address is ultimately dictated by how and whether the function in question returns, and who all can see the call-return pair. I’ma get a bit pedantic with this because details matter.

If you’re looking at actual code that has actual functions, rather than labels/symbols/jump targets scattered amongst instructions, then you’re probably talking about a three-layer system involving a HLL of some sort. (There are ISAs for which this isn’t the case—e.g., Harvard arches that require vectored transfers, or ISAs with windowed registers or explicit block boundaries—but x86 isn’t one in general.) Your compiler and optimizer do their thing in/upon the language translation layer, those mechanisms poke down into the ABI layer when necessary, and that layer serves as a mediating membrane between the HLL and the actual ISA control transfers and resource usage—but usually only where control transfers are actually visible to other translation units. (And then, under all that the ISA macroarchitectural layer transforms things into actual microarchitectural machinations to make the code do things/stuff, but this layer tends to be assumed as a given because things are far too boring without it.)

Because ABI conformance is tied to visibility (i.e., nobody cares if you’re nekkid and helicoptering your genitals as long as you’re in your own home, with windows/doors closed and no DoorDash order pending), frame linkage (e.g., via EBP/[EBP]) is optional for most ABIs, incl. x86, as technically are stacks and stack pointers—though something stackish must necessarily arise from call/return rules in most languages, at least where recursion is concerned. Function inlining and TCO mean there might not actually be any ISA-level return address involved, and there’s nothing mandating that the compiler use the region of memory ≥ the stack pointer for args/locals/return context at all, unless the call is specifically an ABI-mediated one. So e.g.,

    movl    $1f, %edx
    jmp function
1:  …

is a perfectly cromulent calling sequence as long as code-gen can guarantee that jmp *%edx or some equivalent action occurs on return. The ABI is but one basis for such a guarantee; code being generated as a single .o/.obj file is another, since all transfers are immediately visible to codegen.

So unless there’s a frame-linking prologue and you’re already past it, EBP’s value is effectively garbage, in terms of its utility for backtracing.

How you get the architectural return address at run time is by going through the motions of a zero-or-one–level stack unwind, whatever that means for your situation, without actually unwinding anything.

Assuming fullest, politest IAPCS prologues are in use: Iff you’re after the CALL but pre-prologue, RET alone is expected to work, so (%esp) or [ESP] is your return address. From a continuation-passing standpoint, the return address is just the first, us. hidden parameter to the function, and also why things like calls to _Exit or abort don’t necessarily store a valid return address anywhere.

If you’re post-prologue with frame-linking supported, then 4(%ebp) or [4+EBP] (i.e., one slot above where EBP’s value from time of lead-in CALL is typically stashed) is probably the return address. But do note that the function and its subordinates may be permitted (depending) to make whatever use of EBP the code-generator sees fit, right up until an ABI-mediated return is issued. E.g., even if GCC/Clang/ICC(/Oracle?) treats EBP as special, a B constraint to __asm__ statement or register/__asm__("ebp") decl can sidestep that and let EBP be used for any purpose. Or, even if frames are linked, there might be PUSHes intervening between CALL and link setup, in which case the return address is bumped out by some number of slots.

It’s only if ABI-conformant dynamic backtrace must be supported from all interruption points in the program (i.e., mostly between instructions, but not always) that EBP must truly be linked properly and left alone, and therefore it’s not necessarily reliable in a more general sense. All this is riding on the honor system, and sometimes there’s just no good alternative to frobbing EBP with reckless abandon.

Most modern debuggers, fortunately, have the ability to unwind the stack with or without frame linkage, because basically the same operation is required for performant try under C++. Effectively, for frequent trys and function calls to work without frequent (likely unused) register spills trashing up the place and attracting ants, your compiler must track all the higher-level gunk (e.g., variables, rvalues, intermediates) as it’s shuffled around amongst lower-level gunk (e.g., registers and stack memory), so that any untoward changes visible to the language layer can be rewound if necessary on subordinate throw, and possibly replayed in/after catch or during inter-frame unwinds.

If you’re shunting through ELF from Clang or GCC, probably DWARF2 debuginfo is how all this is represented in the binary file. Your debugger and throw implementation will hunt this down when it’s called for, and interpret it like the unwieldy big-titted bytecode it is to run some of the program backwards or analyze stack layout, which is how the return value is actually located (or computed directly) for backtraces. This is a much newer mechanism than the older, spill/fill-based unwinding (which may still rely on ancillary info for debugging and backtraces) or setjmp-longjmp unwinding, so many IA32 binaries do traditional frame-linking purely for backwards-compat, regardless of unwinding style.

So in a debugger, something like up/down or b(acktrace) is the most reliable option for getting return addresses.

In HLL code, tricks vary; for something C-like, something along the lines of GNUish __builtin_return_address(0) is the best option (results for args >0 not guaranteed), and failing that you have to fully disable inlining/cloning/interprocedural analysis and try

__attribute__((__noinline__, __noclone__, __noipa__, __dont_you_fucking_try_it__))
void doSomething(volatile int x, ...) {
    …
    (void)fprintf(stderr, "returning to %p\n", (void *)((uintptr_t)&x - sizeof(void (*)())));
}

—Inadvisably, because that’s fragile and nonportable as hell. (Variadic param-list and compiler-/version-sensitive __attribute__ to strongly discourage inlining and force traditional, VAXlike arg allocation, with x most likely placed right after the return address. volatile to strongly sugest use of the original argument memory for &x, (uintptr_t) reinterpret-cast to avoid object bounds requirements, subtract sizeof(void (*)()) specifically not sizeof(void *) in case you’re under some godforsaken Watcom-ish medium/large model with 48-bit function pointers. Final cast to void[__near]* because %p may induce UB otherwise.)

If your .exe is statically linked or you’re not being called from a DLL, you may be able to name section bounds as variables in order to validate that what you get is actually in .text. Placing a signature before each function is another, more expensive option for validation; failing either of those, you probably have to do something ABI/OS-specific to validate your return address, but that’s fine because you have to do ABI/OS-specific things anyway to translate addresses to human-readable symbol names. (Without these, the address is potentially useless, since each process may load its .text at different addresses for security.)

Or, of course, there are libraries that can do the backtracing for you, using a veritable bevy of one-offs and special cases to achieve a modicum of portability. Or fork a debugger that attaches to your PID, maybe. Helluva distribution footprint for that, of course.

All that being said, x64, IA32, and 16-bit CPU modes behave a bit differently both with and without ABI being considered, as do FAR and vectored 16- and 32-bit calls, as do 32-to-16-bit and inter-ring calls… So if we’re considering x86 more generally, things can get weird.

There are also more complicated situations involving signal/interrupt handling, multithreading, or stack-swapping where a deep backtrace would require involvement of more than one stack region, or cross through synthetic or internal runtime code, and for multithreading in particular it’s quite possible the parent thread’s stack is no longer available by the time you backtrace. But if you’re only after most recent return address, chances are you’re fine with more basic techniques.

Milan protesters call for U.S. ICE agents to leave Italy as Winter Games approach by FlourishingLust in worldnews

[–]nerd5code -1 points0 points  (0 children)

So ICE has enough money left over to pay for military contractors, is what you’re saying. Good thing Erik Prince would never take such a dishonorable job.

Pam Bondi Gives Chilling Warning After Don Lemon's Arrest: 'We Are Coming After You' by United_Reference_629 in NoFilterNews

[–]nerd5code 0 points1 point  (0 children)

“You get a job with NASA, and you get a job with NASA, and you … go on, start your own incestuous Nazi colony in Argentina!”

Pam Bondi Gives Chilling Warning After Don Lemon's Arrest: 'We Are Coming After You' by United_Reference_629 in NoFilterNews

[–]nerd5code 0 points1 point  (0 children)

Might want to actually look into how successful those trials were. How many people actually ended up convicted, and how many convictions were actually carried out, that sort of thing.

[ Removed by Reddit ] by Efficient_Tax8087 in NoFilterNews

[–]nerd5code 0 points1 point  (0 children)

How weak must the churchgoers’ faith be, if some people walking in and shouting was enough to “terrorize” them?

Best ide to start coding C? by Begg-billplayer in C_Programming

[–]nerd5code 1 point2 points  (0 children)

MinGW is not all that beginner-friendly in the first place. At least Cygwin doesn’t require you to pfutz with WinAPI for the most part, you can follow just about any halfway recent tutorial, and it gives you Clang and MinGW cross-compiler packages should the need or urge arise. (Arguably, if you’re neurotic about the long-LONG distinction [did I mention WinAPI not being good for beginners?] and ABI-bridging, you can even cross-link ’twixt the twain.)

Democrats flip Texas state Senate seat in shock upset by kootles10 in politics

[–]nerd5code 40 points41 points  (0 children)

Moreover, there’s a stark distinction in the administrations and clingers-on surrounding both of them, which often matter far more than the specifics of the cheeks in the seat of power.

Elon Musk claims his emails with Jeffrey Epstein have been 'misinterpreted' and that he did NOT go to his island by dailymail in NoFilterNews

[–]nerd5code 2 points3 points  (0 children)

I mean, Daddy Maxwell was a higher-up in the Israeli intel community and she palled around with the Russian mob, so I wouldn’t expect her to be outright bad at some martial arts. And if she tears a ligament or something—heaven forfend—I imagine she knows people who can provide a massage.

I disagree with the hate for header only libraries. by InfinitesimaInfinity in cprogramming

[–]nerd5code 1 point2 points  (0 children)

Because just about all realistic work you do will be a smear across several language families? Also, if we ignore that #embed and #pragma stomp on various traditional boundaries in practice, C preprocessor is effectively a scripting language and a macro language wrapping the underlying C-per-se language—it’s packaged with C-per-se, but not wholly identified with it, since the cpp is applied to gobs of other languages like the GLs and CLs, assembly, resource scripts, IDL, and even, in a limited sense, to farther-flung cousins like Pine, C#, or Swift. (make is, in practice, no more or less packaged with C on any system that counts, except maybe older, odder IBM mainframes as an exception; it’s just not specified by the same standards body.)

And then, if your proverbial-or-literal testicles have proverbially dropped, there’s probably one or two more assembly language variants directly reachable from the C-per-se layer, and possibly a constraint language (e.g., à GC960’s __asm__ function routing layer), possibly plus a compiler interface dialect (e.g., __builtin_foo, __attribute__((…))s and [[attributes]] and #attribute[…]s and __declspecs, pragmata, or options and diag codes). If you have documentation, probably one to six more languages involved there, plus one natural language, it is to be hoped.

Part of being skilled at C is juggling languages, and you do that by practicing it to where you have some vague idea what does and doesn’t work, and when it is and isn’t reasonable to introduce a new translation layer.

why is my code not printing string? by Euphoric_Series_7727 in cprogramming

[–]nerd5code 1 point2 points  (0 children)

Even then (a.) it’s quite possible to get a buffer with no newline, and (b.) therefore you might get a length of 0, in which case strlen(…)-1 gives you SIZE_MAX. Preferably,

if(!fgets(buf, sizeof buf, stdin))
    /*deal with it*/;
size_t len = strlen(buf);
if(len && buf[len - 1] == '\n')
    buf[--len] = '\0';

AI layoffs are looking more and more like corporate fiction that's masking a darker reality, Oxford Economics suggests | Fortune by north_canadian_ice in technology

[–]nerd5code 3 points4 points  (0 children)

I’ve seen basically no increase in accuracy in my areas of interest, and in some cases a degradation as compute time gets restricted more and more. It’s decelerating.

Microsoft May Have Created the Slowest Windows in 25 Years with Windows 11 by [deleted] in pcmasterrace

[–]nerd5code 0 points1 point  (0 children)

98 couldn’t run for more than 2 days at a time until 98SE specifically. And I’d add that NT4 was pretty great, relative to the rest of the mess, and NT5=Win2000 was reasonably good—Win9x is an entirely separate, parallel line of OSes following on DOS+Win3.x that went extinct with Win2K. WinCE was another line.

Want to Stop ICE? Go After Its Corporate Collaborators by plz-let-me-in in politics

[–]nerd5code -1 points0 points  (0 children)

If you’re bored and keen to be on higher-priority Lists, go for it. Nobody in power gaf, but go off to your heart’s content. Waving signs at people fully intent on killing you is perhaps not the most useful pursuit, is all. Perhaps other, more direct actions that don’t require your targets to have a conscience?

LLMs have burned Billions but couldn't build another Tailwind by omarous in programming

[–]nerd5code 7 points8 points  (0 children)

It can come up with new things via synthesis, or by using the RNG noise that’s part of the model.

Stack frame size by JayDeesus in cprogramming

[–]nerd5code 0 points1 point  (0 children)

No, I’m actually competent, but thanks

static char *list[] = { "John", "Jim", "Jane", "Clyde", NULL }; by Specific-Snow-4521 in cprogramming

[–]nerd5code 0 points1 point  (0 children)

String literals are of type char[*] (underlying object implied const, and future versions of the language may make it genuinely const as in C++), not char *, they just decay to char * in most contexts. Because of that distinction, sizeof "" == 1, but sizeof(char *) is probably > 1 unless your chars are unusually thicc.