Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

    <source>: In function 'int main()':
    <source>:6:54: error: conversion from 'absl::string_view' {aka 'std::basic_string_view<char>'} to non-scalar type 'const std::string' {aka 'const std::__cxx11::basic_string<char>'} requested
        6 |   const std::string foo2 = absl::StripAsciiWhitespace(absl::AsciiStrToUpper(foo)); // in Python: foo2 = foo.upper().strip()
          |                            ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ASM generation compiler returned: 1
This is gcc with c++20, curious what the garbage is you're describing.


Oh sorry, foo2 should be auto in this example (which becomes string_view). StripAsciiWhitespace takes a string_view here: https://github.com/abseil/abseil-cpp/blob/master/absl/string...

The garbage comes from AsciiStrToUpper returning a new std::string which StripAsciiWhitespace takes as a string_view (implicit conversion). By the time you print foo2, the string is already freed.


This is a classic misuse of rvalues so I’m not sure it’s a huge problem. I don’t think it’s a problem with C++. I probably work at the same place you do btw and I am pretty sure there are rules/guides about how to handle string_view lifetimes

For those downvoting, please explain why you think string_view should take ownership of an rvalue string


All this talk of rvalues, auto, and string_view is PRECICELY the problem with cpp.

There are so many details you need to keep track of, and eventually you make a mistake. Now, yes, i know what all of that does, and how they are supposed to be used, but it does not remove the cognitive load.

Many languages have a substantially lower cognitive load when doing something trivial, such as ToLower().ToUpper(), etc.


Every systems-level language will have these sharp edges handled differently. Have you heard of borrow checkers? Many languages don’t have to concern programmers with rvalues or equivalents at all because they are garbage collected - should everything be garbage collected?

Let’s not make this a language war, there has to be some programming language that does low-level memory operations without batteries included for some types of technologies. When I write code in C++ and I want something like garbage collection or ref counting I can reach for a shared_ptr.

If you don’t want to concern yourself with types, values vs references, or manual memory management don’t choose C++. The default handling is sane if not necessarily intuitive. You shouldn’t create a ref or pseudo-ref (string_view) to data that is not on the heap and no longer allocated to the stack - seems sane. This problem could be easily caught by breaking function calls into separate lines and explicitly specifying the types at each step.


> Every systems-level language ...

Is Cpp systems-level language? As I see, the problems arrives from the fact that Cpp is a multi-paradigm language, and as such contains a near endless wealth of features to combine. Also modern Cpp takes a clear direction away from low level to (relatively) more high-level language. The problem really comes from the combination of low level and high level paradigms in the same language/codebase, where the expectations of the behavior of each piece of code can vary wildly.

> ... will have these sharp edges handled differently

Perversely, plain C, often has a lower cognitive load than Cpp. This is because you must always manually handle pointers, types, object lifetimes, etc. Now, this does result in a high cognitive load, BUT, the cases as in Cpp where you might combine auto, with a temporary, with a pointer inside, referring to some unseen resource, cannot happen, because you cant do that in C. So the worst case in cognitive load is never as bad as in Cpp. The lack of features means less possible combinations to shoot yourself in the foot. (Though C does still have many, nor is C an ideal language)

> Let’s not make this a language war

Discussing the problems of Cpp is not language war. Nor is understanding the merits and problems of the Design of Cpp.

> If you don’t want to concern yourself with types, values vs references, or manual memory management don’t choose C++

But IF YOU DO write Cpp, there is no escaping them. Which is my point.


Many languages don’t have to concern programmers with rvalues or equivalents at all because they are garbage collected - should everything be garbage collected?

From Xerox point of view, yes. Unfortunely they lost to the UNIX workstation market.

Interlisp-D, Smalltalk and Mesa/Cedar.


There might be a reason they lost.

Believing that one size fits all is a sure way to alienate a lot of people who don't fit that size. Right tool for the right job and giving the freedom for people to solve their problems in the best way is a better way to win people over.


Free beer UNIX on cheaper hardware, plus bad management, basically.

Nothing to do with the technology.

Hence why I love why Android is so locked down to native code, and Apple is doubling down on Swift.


Yeah, you shouldn't have GC in systems-level code any more than I should have lifetime concerns in application-level code. Problem is leaders end up choosing C++ for both and saying y'all should know how to deal with it.

Google also has a lot of stuff in the middle where they're fine with sacrificing a little speed for a lot more safety, but Java etc are too slow. Golang was supposed to satisfy that, but I'm guessing it was too big of a leap from C++.


It's good that you can solve this with 100% of the team following 100% of the time the rules/guides.

It's even better if your language has a way to express "the return value points to data from the input argument, so it's a compile error to pass a rvalue string to this function". The second we got a language able to do that, usable everywhere where C++ is, (yes, that one) the incapacity of C++ to express this became "a problem with C++". Our expectations have just increased.

Surely it can be catched via static analysis if you suppose the common case that the return value is a function of the argument, and not pointing to some static global data. But you will get false positives when somebody does the uncommon case. There is a lack of expressiveness in C++ here.


The "oh shit" moment when we found that our database's indexes got mysteriously corrupted and we had no idea from where. What do we do, fire the entire team to get rid of whoever made the bug?


But C++ can express that, with compiler extensions:

https://godbolt.org/z/ohxaGzsEM


That's cool.

Last I remember, the lifetime profile stuff was there, but there was still no way to add your own annotations. For some reason, I didn't hear too much about any of this, it was

- clang is working on it

- clang is working on it

- clang is working on it

- Visual Studio has it

- clang is working on it

- Silence

gcc still has nothing, right?


I have just taken a look... https://wg21.link/p1179 is actually still not there, right? I see some interesting stuff in https://discourse.llvm.org/t/rfc-lifetime-annotations-for-c/... from last year. But, in general... once Herb started the whole Lifetime safety profile thing, there seemed to be a lot of interest, but for the last few years things seems to have died? I think things are better with Visual Studio, but being on Linux... I may need to start developing for Linux from Visual Studio with WSL2 :-(


Only VC++ is working on it, the clang tidy developer looking into lifetime has moved on.


That's just sad.


When you're writing a ton of web backend code dealing with strings all over the place, it's easy to forget to check whether something is accepting and returning a string or string_view. `auto foo2 = StripAsciiWhitespace(AsciiStrToUpper(foo))` doesn't say what's going on.

I didn't downvote, btw. I don't do that in general.


Heh this is normally why I tell my new teammates to be careful about using auto in non-test code outside of well established patterns like iteration. Auto will bite everybody in the butt at some point!


We don't got time for non-auto. Better yet, we should've just written all our stuff in Python or Java. We have no legitimate need (performance etc) for C++, Rust, or even Golang.

Even if you use string_view on the LHS instead of auto, pretty easy to miss the bug here.


Same here. I avoid auto in my code except iterations. Just a mental pattern. I understand that people coming from "typeless" languages might not like it at all, but it is like with guns. You can play with water pistol but you do not play with real guns, you follow some rules if you want it safe. Modern C++ in my opinion supplies enough features and tooling to help with making reasonably sure the rules are followed.


auto is the least of your worries when it comes to memory safety in C++.


Classic C++


And yet "Almost Always Auto" is "Modern C++"...


Citation needed? My team generally avoids auto and tends to spell out the types most of the time, which we find makes everything more readable. Code is written once but read many times...


A citation of what's "Modern C++"? The term is a made up concept with no proper definition...

But "Herb Sutter says you should use it, he even gave it a catchy name/acronym" is as good as it gets. And he does so AFAIK in the same place he created the "Almost Always Auto" name: https://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style...

Notice that he says "the main reasons to declare variables using auto are for correctness, performance, maintainability, and robustness—and, yes, convenience, but that’s in last place on the list.". He is arguing literally the opposite of what you do, that using auto avoids bugs ("for correctness").

I'm not going to argue in favour or against "Almost Always Auto". But I see no problem calling it "Modern C++".

* Herb Sutter being the convener of ISO WG21


imo types don't make things more readable. You know the "fluent programming" thing where you do obj.doThis().doThat().doThis().doAnotherThing() and probably 20 more lines of this? That's entirely because people didn't want to bother writing out LHS types, but whatever version of the language only let you avoid that if you chained things (there was no auto or var). Maybe it's more of a Java practice, though.


Your local style guide can’t override this?

Just turn people loose on your codebase without supervision and be really surprised that the hackers make off with your data?

You, sir, are arguing from bad faith as your obvious mission is to promote “rust in all the places”.


Our style guide says "almost never auto," but most people auto everything. They can make the linter replace auto with the actual type if it's really that big a deal. Explicit type wouldn't have avoided this bug.


Arguably an explicit type would have made the bug a little bit more obvious. You basically expect, by default, this kind of string manipulation functions to return a std::string. Obviously in this specific case you can return a view, and that makes it more performant; but it's kind of unexpected and using auto leaves the surprise a bit more hidden.

But sure, you can still make the error with expiclit types.


I agree, the string_view on the LHS might make you think more about the lifetime, but I'm pretty sure we all would've missed it.




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

Search: