Hacker Newsnew | past | comments | ask | show | jobs | submit | maccard's commentslogin

I think it's clearly back compatability.

It still is for a lot of Mac Apps. You download a DMG, and you get somethinglike [0] where you drag the icon over, and it installs. The last app I uninstalled also removed the matching Library Support folders, which was neat!

[0] https://stackoverflow.com/questions/8680132/creating-nice-dm...


Azure container apps are a great (idea) and work mostly fine as long as you don’t need to touch them. But they’re just like GCR or what fargate should be - container + resources and off you go.

We ran many internal workloads on ACA, but we had _so may issues_ with everything else around ACA…


> Standardizing the build system and toolchain needs to happen. It's a hard problem that needs to be solved.

I agree, and I also think it’s never happening. It requires agreeing on so many things that are subjective and likely change behaviour. C++ couldn’t even manage to get module names to be required to match the file name. That was for a new feature that would have allowed us to figure out esports without actually opening the file…


The problem is doing this requires a team to support it that is realistically as large as your average product team. I know Bazel is the solution here but as someone who has used C++, modified build systems and maintained CI for teams for years, I have never gotten it to work for anything more than a toy project.

I have several times built my own system to do just that when it wasn't even my main job. Doesn't take more than a couple of days.

Bazel is certainly not the solution; it's arguably closer to being the problem. The worst build system I have ever seen was Bazel-based.


> I have several times built my own system to do just that when it wasn't even my main job. Doesn't take more than a couple of days.

Really? I'd love a link to even something that works as a toy project

> Bazel is certainly not the solution; it's arguably closer to being the problem. The worst build system I have ever seen was Bazel-based.

I agree


It usually ends up somewhat non-generic, with project-specific decisions hardcoded rather than specified in a config file.

I usually make it so that it's fully integrated with wherever we store artifacts (for CAS), source (to download specific revisions as needed), remote running (which depending on the shop can be local, docker, ssh, kubernetes, ...), GDB, IDEs... All that stuff takes more work for a truly generic solution, and it's generally more valuable to have tight integration for the one workflow you actually use.

Since I also control the build image and toolchain (that I build from source) it also ends up specifically tied to that too.

In practice, I find that regardless of what generic tool you use like cmake or bazel, you end up layering your own build system and workflow scripts on top of those tools anyway. At some point I decided the complexity and overhead of building on top of bazel was more trouble than it was worth, while building it from scratch is actually quite easy and gives you all the control you could possibly need.


This is all great, but it doesn’t sound simple or like 200 lines of code.

Jira’s problem is that it’s effectively free-form, and there are no enforcements in place. You can have three teams - one using kanban with relative estimates, another using springs with story points, and a third using waterfall with time estimates - all in the same project, with the same workflows, and conflicting requirements. You have 3 different release fields, 2 are required, the third one is the one that your team are generating reports from.

That and its dog slow, of course.


The answer is unfortunately jira.

I want my compiler, language server IDE, to do that not LinkedIn

My company started using slack in 2015 and at that time I put in a bug report to slack that their desktop app was using more memory than my IDE on a 1M+LOC C++ project. I used to stop slack to compile…

The bug in Slack is that it uses Electron

Electron has been a blessing and a horrible thing at the same time.

The overhead added by Electron is hardly that significant at this point, you can still use it to write significantly more efficient apps

The overhead of an entire browser engine isn’t significant compared to a native app?

No, compared to everything else in those apps. i.e. if they are writing extremely bloated Electron apps why would the native version be less slow and bloated? I mean Electron's overhead is mostly fixed (it's still a lot but its possible to keep memory usage we below 1 GB or even 500 BB even for more complex applications).

A native app that compiles to machine language and uses shared system libraries is by definition going to take less memory and resources than code + web browser +Javascript VM + memory to keep JITd byte code.

Write a “Hello World” in C++ that pops up a dialog box compared to writing the same as an Electron app.


Yes, exactly, that's what I said. There is significant overhead but is it the only or the main reason why these apps are so slow and inefficient? It's perfectly easy to write slow and inefficient code in C++ as well...

Exactly how would you write a program in C that could possibly be as bloated as adding an entire browser engine + Javacript runtime?

A highly inefficient render loop. I've seen people commit absolute crimes rendering text in game engines.

This is not what "by definition" means.

A - your code

B - a heavy runtime that is greater than 0

C - system libraries

By definition

A + C < A + B + C


Again, this is not by definition. This is by deduction.

It's always good to not slack when compiling.

Just to clarify for other readers, sword fighting while riding office chairs is not slacking.

Indeed.

   bool is_even(int* valPtr) {
      assert(valPtr != nullptr);
      return *valPtr % 2;
    }
Does not do what you think it does with nullptr. A major game engine [0] has a toggle to enable asserts in shipping builds, mostly for this reason

[0] https://dev.epicgames.com/documentation/en-us/unreal-engine/...


Let's not vague post on HN. What's the problem with the above?

The problem is the code unconditionally dereferences the pointer, which would be UB if it was a null pointer. This means it is legal to optimize out any code paths that rely on this, even if they occur earlier in program order.

But if the assertion fails, the program is aborted before the pointer would have been dereferenced, making it not UB. This explanation is bogus.

Only if the assert is active. It basically means that the code is invalid when NDEBUG is set.

When NDEBUG is set, there is no test, no assertion, at all. So yes, this code has UB if you set NDEBUG and then pass it a null pointer — but that's obvious. The code does exactly what it looks like it does; there's no tricks or time travel hiding here.

> it is legal to optimize out any code paths that rely on this, even if they occur earlier in program order.

I don't think this is true. The compiler cannot remove or reorder instructions that have a visible effect.

  if (p == 0)
    printf("Ready?\n");
  *p++;
The printf() can't be omitted.

> The compiler cannot remove or reorder instructions that have a visible effect.

You might be surprised! When it comes to UB compilers can and do reorder/eliminate instructions with side effects, resulting in "time travel" [0].

IIRC the upcoming version of the C standard bans this behavior, but the C++ standard still allows it (for now, at least).

[0]: https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=63...


No, this is explicitly legal. Most compilers will shy away from it these days since it made a lot of people upset, but it's definitely allowed.

> The problem is the code unconditionally dereferences the pointer, which would be UB if it was a null pointer.

Only when NDEBUG is defined, right?


No, the code that does this is always active

Right so strictly speaking C++ could do anything here when passed a null pointer, because even though assert terminates the program, the C++ compiler cannot see that, and there is then undefined behaviour in that case

> because even though assert terminates the program, the C++ compiler cannot see that

I think it should be able to. I'm pretty sure assert is defined to call abort when triggered and abort is tagged with [[noreturn]], so the compiler knows control flow isn't coming back.


Shouldn't control flow diverge if the assert is triggered when NDEBUG is not defined? Pretty sure assert is defined to call abort when triggered and that is tagged [[noreturn]].

Sorry, yes, I misread you

I'm sorry, but what exactly is the problem with the code? I've been staring at it for quite a while now and still don't see what is counterintuitive about it.

There's nothing wrong with it. It does exactly what you think it does when passed null.

A lot of compilers will optimize out a NULL pointer check because dereferencing a NULL pointer is UB.

Because assert will not run the following code in the case of a NULL pointer, AFAIK this exact code is still defined behavior, but if for some reason some code dereferenced the NULL pointer before, it would be optimized out - there are some corner cases that aren't obvious on the surface.

This kind of thing was always theoretically allowed, but really started to become insidious within the past 5-10 years. It's probably one of the more surprising UB things that bites people in the field.

GCC has a flag "-fno-delete-null-pointer-checks" to specifically turn off this behavior.

https://qinsb.blogspot.com/2018/03/ub-will-delete-your-null-...

This is an actual Linux kernel exploit caused by this behavior where the compiler optimized out code that checked for a NULL pointer and returned an error.

https://lwn.net/Articles/342330/


Sure, but none of that is relevant to just the code snippet that was posted. The compiler can exploit UB in other code to do weird things, but that's just C being C. There's nothing unexpected in the snippet posted.

The issue is cause by C declaring that dereferencing a null pointer is UB. It's not really an issue with assertions.

You can get the same optimisation-removes-code for any UB.


> There's nothing unexpected in the snippet posted.

> The issue is cause by C declaring that dereferencing a null pointer is UB. It's not really an issue with assertions. > You can get the same optimisation-removes-code for any UB.

I disagree - It’s a 4 line toy example but in a 30-40 line function these things are not always clear. The actual problem is if you compile with NDEBUG=1, the nullptr check is removed and the optimiser can (and will, currently) do unexpected things.

The printf sample above is a good example of the side effects.


> The actual problem is if you compile with NDEBUG=1

That is entirely expected by any C programmer. Sure they named things wrong - it should have been something like `assert` (always enabled) and `debug_assert` (controlled by NDEBUG), as Rust did. And I have actually done that in my C++ code before.

But I don't think the mere fact that assertions can be disabled was the issue that was being alluded to.


I wrote the comment, assertions being disabled was exactly what was being alluded to.

> that is entirely expected by any C programmer

That’s great. Every C programmer also knows to avoid all the footguns and nasties - yet we still have issues like this come up all the time. I’ve worked as a C++ programmer for 12 years and I’d say it’s probably 50/50 in practice how many people would spot that in a code review.


It's definitely a footgun, but the compiler isn't doing weird stuff because the assertions can be disabled. It's doing weird stuff because there's UB all over the place and it expects programmers to magically not make any mistakes. Completely orthogonal to this particular (fairly minor IMO) footgun.

> I’ve worked as a C++ programmer for 12 years and I’d say it’s probably 50/50 in practice how many people would spot that in a code review.

Spot what? There's absolutely nothing wrong with the code you posted.


That assert could completely fail to fire if inlined into another function that did a dereference first.

Depends on where you're coming from, but some people would expect it to enforce that the pointer is non-null, then proceed. Which would actually give you a guaranteed crash in case it is null. But that's not what it does in C++, and I could see it not being entirely obvious.

Assert doesn't work like that in any language.

It does in Rust: assert is always enabled, whereas the debug-only version is called debug_assert.

But yes, “assert” in most languages is debug-only.


He said

> some people would expect it to enforce that the pointer is non-null, then proceed

No language magically makes the pointer non-null and then continues. I don't even know what that would mean.


If you don't even know what that would mean then it's premature to declare that nothing works that way. Understanding the meaning is a prerequisite for that.

In this case, it may help to understand that e.g. border control enforces a traveler's permission to cross the border, then lets them proceed.


This is a very "Dr Dr it hurts when I do this" "Don't do that" one it must be said.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: