Programming thread

He's isn't a senior but he's been on that project for so long that it's expected of him to know when it's appropriate to push directly to master.
It's never appropriate to push directly to master.
Even if it's 3AM and everything is on fire. You can spend the 3 extra minutes for a branch. Even if you make and approve the PR yourself.
 
It's never appropriate to push directly to master.
Even if it's 3AM and everything is on fire. You can spend the 3 extra minutes for a branch. Even if you make and approve the PR yourself.
The senior for this project seems to think it's okay in certain circumstances. I think he's wrong but he's been at the company since forever and I started relatively recently so I'm not gonna tell him how he runs things is wrong lol.
 
He's isn't a senior but he's been on that project for so long that it's expected of him to know when it's appropriate to push directly to master. It isn't deliberate he's just retarded and/or lazy and I hear the boss (the actual senior) getting more and more fed up with him in our meetings.
The fault honestly lies on his manager for retaining his maintainer rights in that scenario, should be automatic grounds to restrict his account. I've got code owner rights over one of my company's projects but couldn't ever justify pushing changes like that outside of approved code reviews - besides senior management would have my head for even contemplating it.
 
Can anyone recommend a good web forum for asking C++ related questions?

Since StackOverflow seems useless to me...
I gave StackOverflow another try recently, and asked a question there about a real-life software engineering problem that surely others must have faced before.
I outlined the solution I was going for, and asked if going down that path would lead to critical obstacles that I had failed to consider.

I got a single, short, smug response that completely ignored the contraints I had mentioned (existing codebase, third-party libraries...) and simply told me that everything should have been done differently from the start (which I had no control over btw) so that I would not face this problem.

Then the close-votes came coming in, and StackOverflow's volunteer mods (who would make rules-lawyering Wikipedia editors proud) closed my question as "out of scope" for soliciting "opinion based" answers.
(As if actual experience-based knowledge that certain obstacles/limitations exist, would be merely some useless "opinion"!)

Fuck me for asking a question that can't be answered by citing a sentence from cppreference.com, right? Because those kinds of questions sure do well there:
  • Pajeet asks "How [simple language feature] work?" or "What [standard library function] do?"
  • Another pajeet copy&pastes the summary paragraph and example from that feature's cppreference page.
  • Both question and answer get thousands of upvotes.
  • The SO question becomes the C++ feature's top Google result (which had previously been the cppreference page itself). SO management's eyes become dollar signs as those sweet, sweet ad views pour in.
  • Retarded hiring managers think that the two pajeets in question must be super competent and experienced if they have such a high SO score. Their new colleagues will have to pick up the slack.
  • Sigh. I admit I got a bit side-tracked there.

Are there still good C++ websites around that do value practical programming experience/wisdom and those who seek it?
PS: And ideally, isn't completely overrun with drama-seeking trannies.
 
Last edited:
Pointers are an essential concept, IMO, and languages without pointers are like typing with mittens. They're also an extremely *simple* concept, and I can't wrap my head around why some flavor-of-the-week template class is somehow less mental overhead than calling delete[] in the destructor or the end of a function where you allocated with new.
And what if I need to pass this pointer around to multiple parts of my program? What if my operations on this data structure can and do happen out of order so I no longer know at which point in the program flow is it safe to deallocate this data structure? Concurrent access?

Maybe I can have some kind of, internal variable that keeps track of how often I hand out pointers... like some kind of counter... for references... :thinking:

This absolutist attitude is just extremely bad. For small simple programs, sure, you can manage your own memory. It's even preferable in many cases. But at a certain point you're going to end up just half-writing your own reference counter or garbage collector to do the things that using RC/GC gets you for free. Greenspun's tenth rule is just as true today as it was in 1990.

EDIT: I'm going to sperg even harder. malloc/new and free/delete aren't even especially low-level things. Like there's no malloc circuitry in your processor. Malloc uses a linked list internally to keep track of which segments of memory have been allocated. When you call malloc, it searches this linked list to determine if there are any gaps in pre-allocated memory that your new allocation can fit into (yes, memory allocated with malloc() is subject to fragmentation like a hard drive in the 90s). If it can't find a place to fit your new allocation, it'll call sbrk or mmap (or whatever the equivalent is in the OS you're working in) to increase the size of the heap and add it to the end of the list in the newly expanded heap.

Free/delete works the same way, just with removal from that list. And crucially, because memory allocated with malloc can become fragmented over time if it's not reorganized periodically, then free'ing large data structures might not even give memory back to the OS because you might just open large gaps between two active allocations in the heap.

This is why GC languages like Java and C# can actually compare favorably with non-GC ones like C and C++ when you start writing programs at scale, because a lot of this memory reorganization is efficiently amortized over the lifetime of the program.
 
Last edited:
My biggest gripe with SO is that a lot of the time, people will ask "How do I do X using Y?" and most of the answers will be "You should use Z instead". This absolutely poisons search engine results
The XY Problem is why I virtually never ask a question about anything on the Internet. I would literally rather spend an hour (or more) searching for an answer rather than have some greasy neckbearded faggot give me the "Well, ahkshually..." routine.
 
This is why GC languages like Java and C# can actually compare favorably with non-GC ones like C and C++ when you start writing programs at scale, because a lot of this memory reorganization is efficiently amortized over the lifetime of the program.

Up to a point, maybe. It's possible to have a C or C++ program that's bottle-necked by allocations and the like, and it's nearly always possible to solve this once you've diagnosed it. With GC languages, you're fucked.
 
Up to a point, maybe. It's possible to have a C or C++ program that's bottle-necked by allocations and the like, and it's nearly always possible to solve this once you've diagnosed it. With GC languages, you're fucked.
Yes, in terms of memory allocation complexity, I basically break programs down into three classes:

1) Small programs that do relatively little dynamic memory allocation. These are best served by using C's built-in malloc/free and mmap. It's also not a bad approach if you're writing a small, performance critical bit of code that can safely encapsulated into a shared object and loaded by a higher-level language at runtime for better performance.
2) Medium-sized programs that do a lot of dynamic memory allocation but without a ton of performance constraints. These are best served by simply leveraging an existing automatic memory management system. Most 'large' applications your average developer will write will never leave this category.
3) Medium-and-larger programs that do a lot of dynamic memory allocation but also have performance constraints that border on realtime. For this class of programs, you'll likely need to reimplement large swaths of libc and tune them yourself. This is the sort of thing that web browsers do.

Basically if you're getting into territory where garbage collection/reference counting isn't cutting it, then you're probably not going to go back to free/malloc but instead implement them yourself.
 
Up to a point, maybe. It's possible to have a C or C++ program that's bottle-necked by allocations and the like, and it's nearly always possible to solve this once you've diagnosed it. With GC languages, you're fucked.
Not in the general case. The issue is with object allocations with cycles and non-trivial lifetimes.

If you've got complex data structures like that and your algorithm is complex enough, without a real garbage collector (with the cycles, reference counting won't do), you have to pick one of:
  • Code that clearly expresses your algorithm
  • Efficient memory usage
If you want efficient memory usage, you'll need to hypermanage every function call and function return (and how they handle errors), and make sure however you arrange allocation, it's done correctly and nothing leaks. This is cluttery as fuck, and especially brittle. Change things or experiment a bit, and you have a good chance of introducing memory leaks. Don't work on this kind of code if you're sleepy.

Or you could go with some kind of reference counting, which works, but if your data structures have cycles, you end up allocating too much or holding on to too much longer than is necessary.

A garbage collected language lets you get much more efficient memory usage as well as very clear code. It won't get memory usage as efficient as the hand written stuff, but it gets surprisingly close. And eliminating the possibility of whole class of bugs is very nice.

I think garbage collection gets a bad rap for performance not because of GC itself, but because most programmers associate it with dynamically typed languages like Javascript and Python. Those languages are incredibly inefficient because of the multitude of places that type checking has to be employed. (even with clever optimizations in their compilers, there's just not the same information available compared to statically typed languages)

When you include typing, the main disadvantage to garbage collection is the GC pause.

This is an interesting comparison between a GC'd, statically typed language and C++. The GC'd language is competitive with C++, although this mostly touches on speed, not memory allocation efficiency, but still interesting, I think.
 
At my job today one of my coworkers pushed broken code, which clearly failed several tests, at the end of the day and just left it like that. Now me and nobody else in the team can deploy their work until this fucking tard fixes whatever it is he broke. Just how much of a fuck up do you have to be to hold up everyone else's progress like that? It's not hard to: write code, test it locally, see that it's broken and not push that broken shit out.
How do you deal with tech retards?
My advice would be to use GitHub actions to force unit tests to be ran before a PR can be merged. Never allow direct pushes to master.

If your coworker is not writing acceptable unit tests or showing proof that he is testing manually, that is a discussion you need to have with them and eventually your team lead if they don't improve.
 
My advice would be to use GitHub actions to force unit tests to be ran before a PR can be merged. Never allow direct pushes to master.

If your coworker is not writing acceptable unit tests or showing proof that he is testing manually, that is a discussion you need to have with them and eventually your team lead if they don't improve.
This is an organization problem. There's many different technical and process ways to prevent stuff like this from happening. In this case, because it happened, means that either pushing to master has managements blessing, or the person in question has management. Sad truth is, you can't solve a organizational problem with technical solutions. The best thing in this case is to make sure management understands why this is such a huge fuckup. Unfortunately in my experience, that's much harder than setting up branch protection
 
The XY Problem is why I virtually never ask a question about anything on the Internet. I would literally rather spend an hour (or more) searching for an answer rather than have some greasy neckbearded faggot give me the "Well, ahkshually..." routine.
I found that using ChatGPT for programming questions is surprisingly efficient. Whether it's boilerplate code that was written a billion times, or in depth "what is preferable X or Y", it actually answers your question rather than engage in high school politics. It helps that Google is so fucking bad because of preferring SEO over what you are actively searching for.
 
When you include typing, the main disadvantage to garbage collection is the GC pause.
This can sometimes death spiral you with servers though, so it is a bit of a downside (need to GC, pause, more requests come in while paused, need to GC again...)

This is sort of an edge case though
 
  • Agree
Reactions: Marvin
I think garbage collection gets a bad rap for performance not because of GC itself, but because most programmers associate it with dynamically typed languages like Javascript and Python. Those languages are incredibly inefficient because of the multitude of places that type checking has to be employed. (even with clever optimizations in their compilers, there's just not the same information available compared to statically typed languages)

If GC sped up code, you'd expect to see it used in C++. Instead, C++ recently removed its (unused) garbage-collection bindings, and stuff like boehm-gc is very niche (Inkscape comes to mind as one of the few programs that uses it).

GC is largely there to allow pajeets to write code cheaply without fucking things up too badly.
 
Last edited:
This can sometimes death spiral you with servers though, so it is a bit of a downside (need to GC, pause, more requests come in while paused, need to GC again...)

This is sort of an edge case though
Yeah I mean, it's just a place to start.

It might work with default settings, or you might need to dig into the manual for your language/runtime and play with the GC algorithm settings. Do some benchmarks, tune it to your specific workload.

It's a tool, not magic.

One of my favorite programming books is for Ocaml and it goes into the theory of the language, obviously, but also dedicates a lot to the practical specifics about how the language and runtime are implemented. None of this "lol it's magic, ignore the compiler" nonsense.
 
This absolutist attitude is just extremely bad. For small simple programs, sure, you can manage your own memory. It's even preferable in many cases. But at a certain point you're going to end up just half-writing your own reference counter or garbage collector to do the things that using RC/GC gets you for free. Greenspun's tenth rule is just as true today as it was in 1990.

I'm not so much absolutist about a specific use of pointers, than I am absolutist about them being available and under the programmer's control. I have a few patterns that work for me. If I were to write my own reference counter, I'd at least know that it would free memory when I tell it to, instead of doing some mysterious thing hidden in the bowels of some complicated management system/someone else's class. Or just ignoring all my commands to free this damn memory.

(Thinking mostly of a pytorch NN training program I was playing with. I'm not as familiar with pytorch, but one of the problems is that the math-looking interface presented to the user is the tip of some iceberg of actual implementation that is obscure. (Building up some network graph. In recurrent networks, the graph "loops back onto itself." (is unrolled across some finite length of input/output)) I was trying to train a recurrent thing, and could not get it to deallocate certain memory no matter how many unlinking/garbage-collection invocations I made. I knew what I wanted pytorch to do. I did not know how to get pytorch to do it.)

One interesting pattern that I sort of stole from LAPACK and a bunch of old fortran programs in this large-integer arithmetic/cryptography library that I've been writing is this:

If you allocate all your memory upfront, and only once, in the top level set of functions exposed to the user, and just pass buffers of working memory (of a known deterministic size that is a function of the operand sizes) to all your subroutines, then things run much faster because there is no overhead for allocating/deallocating memory in all the fiddly iterative steps. Also you can check that everything got allocated upfront, and there are no mysterious bugs/hacks that can be triggered by unusual input. (Though there do need to be many checks for corner cases, fuzzing tests, etc.)

int libname_somefunction_ui32ll(uint32_t *ain, uint32_t *bin, uint32_t *cout, uint32_t *wrk, int inputlength)
// Inputs, outputs, and wrk are each some fn(inputlength) in size
// the low level functions are in a C library, the higher level wrapper library is in C++

then wrk gets parted out and passed to further subroutines as the calculation proceeds
uint32_t* wrkd = &(wrk[0+someoffset]);
uint32_t*wrke = &(wrk[2*inputlength+someoffset]);
...

It's actually ended up faster than the numerical library built into the compiled portion of the python language in a few tests, and I'm not doing anything horribly different in terms of algorithms. (Going off of handbook of applied cryptography mostly.)
 
Last edited:
Another common gripe I have with programming questions/answers found on the Internet:
When someone asks a question about performance, like:

"Is X generally faster than Y?"

And inevitably, some smartass comes along and responds:

"Well have you tried it?
Just write a short program to try it, bruh!"

I always want to reach through my screen and strangle that second person.

Writing meaningful performance unit-benchmarks is hard!
It's its own art form, that most developers are not proficient in. (I know I'm not.)

You can easily fall into the trap of writing a benchmark where the work you think you're measuring gets optimized out by the compiler, so you're measuring a null-op.
Or otherwise interacts with the optimizer differently than it would in the context of real-life code.
Or becomes noise compared to the overhead of the benchmark boilerplate you added.
Or behaves differently under your test input data than with realistic data.

And even if the newbie question asker were to somehow avoid all the pitfalls and write benchmarks for X and Y that are meaningfully comparable to each other and transferable to real-life usage patterns, they'd just still run them on their developer machine and thus have one data-point.

Or even if they managed to test many hardware/OS combinations, they'd still not understand why the performance difference (or lack thereof) manifests, and thus cannot learn from it.

There is much valuable experience behind a proper answers like:

"Algorithm X has logarithmic complexity and Y quadratic, so for sufficiently large inputs, X must be faster. But Y avoids [constant overhead] and has an extremely cache-friendly memory access pattern, and thus will be faster on modern machines for inputs sizes of up to at least a few thousand, except under [unfavorable conditions]."
or
"Expression X can be compiled into a single fast instruction on x64 CPUs provided that [conditions] are met, and all modern compilers except MSVC tend to successfully do that - whereas expression Y cannot because [reasons] and is thus slower under those conditions."

I respect that kind of shit a lot.

But there's always one midwit who thinks they're helping™ by being the first to answer the question with a "Hurr Durr just quickly try it out and see which one is faster!"
I don't resent them for not knowing the proper answer (I often don't);
I resent them for not being able to imagine that the proper answer exists.
 
The senior for this project seems to think it's okay in certain circumstances. I think he's wrong but he's been at the company since forever and I started relatively recently so I'm not gonna tell him how he runs things is wrong lol.

Every software company's technological upper limit is defined by moronic practices senior developers are allowed to get away with because challenging them just gets you sent out the door.

And what if I need to pass this pointer around to multiple parts of my program? What if my operations on this data structure can and do happen out of order so I no longer know at which point in the program flow is it safe to deallocate this data structure? Concurrent access?

You could abuse std::shared_ptr like a retard, I mean, we're talking about commercially deployed code here, you should ideally find the most retarded possible implementation and then defend it until the day you die, preferably driving out some really talented, younger developers along the way.
 
Last edited:
Back