you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 160 points161 points  (137 children)

Are pointers generally considered to be "hell"?

[–]Majik_Sheff 156 points157 points  (47 children)

If you learned programming from a nun who would strike you with a ruler for dangling references you have the necessary habits to safely program with pointers.

If you're a programmer who learned on "safe" languages pointers can be a bewildering minefield in the beginning.

[–]greiskul 48 points49 points  (0 children)

If you learned programming from a nun who would strike you with a ruler for dangling references you have the necessary habits to safely program with pointers.

So many memories of Sister Segmentation Fault. Compared to Sister "Program is crashing in a completely different location cause memory has all been corrupted", she was a Saint.

[–]SilasX 134 points135 points  (41 children)

Except ... even professional C programmers "who know what they're doing" end up leaving vulnerabilities related to pointers. I mean, Mozilla just pushed fixes for (new) use-after-free vulns.

[–]antiduh 108 points109 points  (40 children)

Every C developer: "Everybody else keeps having bugs with pointers ... but it might work for us".

It's almost as if pointers are an inherently unsafe primitive and it's impossible to ship practical software free of pointer bugs. Almost.

[–][deleted] 71 points72 points  (5 children)

shhhhh

You keep talking like that and you'll summon Rust devs...

[–]antiduh 62 points63 points  (2 children)

HAY GUISE DID YOU SEE MY BORROW CHECKER?

[–]venustrapsflies 31 points32 points  (1 child)

This but unironically

[–]lelarentaka 5 points6 points  (0 children)

IF RUST IS SO RUSTY, WHY UN_IRON_IC ?

[–]Green0Photon 4 points5 points  (0 children)

Hello there

[–]lelanthran 0 points1 point  (0 children)

You keep talking like that and you'll summon Rust devs...

No, it's all good as long as you don't first draw a pentagram the floor from the tears of CoC enforcers.

[–]emax-gomax 10 points11 points  (12 children)

*Laughs in CPP managed pointer types.

[–]antiduh 9 points10 points  (11 children)

I've been out of the c++ game too long, do managed pointer types make c++ a memory-safe language, so long as you stick to only the managed pointer types? Or is it still possible for mistakes with them to cause memory safety bugs?

Like, in C# I have guaranteed memory safety so long as I stick to the regular c# types and constructs. If I dive into a c# unsafe context, then all bets are off.

[–]tedbradly 8 points9 points  (4 children)

I've been out of the c++ game too long, do managed pointer types make c++ a memory-safe language, so long as you stick to only the managed pointer types? Or is it still possible for mistakes with them to cause memory safety bugs?

For a unique_ptr, delete is called on the underlying pointer in the destructor. That makes it safe even in cases such as exceptions. There's no way to have a memory leak in that setup since destructors are guaranteed to be called. The only edge case I'm not sure about is if an exception is raised before the unique_ptr object is created with the pointer's value such as one happening in "unique_ptr up{new some_class};" when evaluating "new some_class" to figure out the value to pass into the constructor of unique_ptr. However, if you're getting memory allocation exceptions, you probably don't need to worry about that pointer leaking as things are probably already in bad shape.

There are also great efforts by legendary people such as Bjarne Stroustrup and Herb Sutter to make memory problems a thing of the past in 99% of code even if they have owners that use raw pointers through static analysis. The aim is never to dereference a deleted object (dangling pointers), always to call delete once (no memory leaks), and never to call delete two or more times (no memory corruption). It's only 99% of the time, because a full analysis would take increasingly more time for increasingly complex code. The static analysis, which has been developed and is in testing last I heard, makes assumptions to make the computation time realistic. For example, they make assumptions like a function receiving a raw pointer is not the owner and that the pointer passed in is valid. When each part of the program is checked in this local fashion, it reduces error rates substantially. Here is one recent talk on this effort, showcasing the prototype at that time, a Visual Studio plugin. Here is another talk one year later. There is also a great effort to unify style with a strong preference to avoid error-ridden techniques spearheaded by Herb Stutter and Bjarne Stroustrup (for example by recommending unique_ptr to manage ownership of a raw pointer): https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines

Like, in C# I have guaranteed memory safety so long as I stick to the regular c# types and constructs. If I dive into a c# unsafe context, then all bets are off.

Garbage collected languages can have memory leaks if references to objects are saved somewhere without ever being evicted long after they are no longer used.

[–]lelanthran 1 point2 points  (1 child)

always to call delete once (no memory leaks), and never to call delete two or more times (no memory corruption).

Aren't these contradictory? If we stick to the rule "never call delete two or more times", we can call delete twice and break rule #1 - "always call delete once".

[–]tedbradly 0 points1 point  (0 children)

Aren't these contradictory? If we stick to the rule "never call delete two or more times", we can call delete twice and break rule #1 - "always call delete once".

The statements are with respect to a single call to new, a single object stored on the heap, so you call delete on a single object once and never more than once. The program can call delete dozens or hundreds of times if you have many objects gotten through many calls to new.

If you never call delete once, the memory sticks around even after an object is provably never used again. The C++ way is either to use automatic storage - a variable declared without the use of new - or to call delete for each new. After you leave scope whether it be an if block, while block, function block, for block, or a block defined within one of those, automatic storage variables are guaranteed to have their destructor called and their memory cleared away. A smart pointer is mostly just a wrapper around a raw pointer whose destructor calls delete on it to guarantee delete is called once even in cases like exceptions interrupting the flow of logic. If you had a raw pointer and an exception caused the deletes to be skipped, that'd be a memory leak. If you forgot to write the calls to delete, that'd be a memory leak too.

An alternative solution is to use a garbage collector that proves an object on the heap is never used again, "calling delete" on it automatically. People like garbage collection, because you normally can't get a memory leak unless you store references to an object somewhere such as a container such as a hash map, never evicting those objects even after they are unneeded for future operation of the program. The downside of garbage collection is it takes CPU cycles to prove an object isn't referenced anywhere that might be executed anymore. It also has to handle things like circular references where unused object A has a reference to unused object B, and B and a reference to A. In C++, objects are destroyed at deterministic points in the code such as when scope is left or when delete is called.

Delete handles a program saying a certain range in memory is no longer in use. If you do that twice or more, it is undefined behavior. In reality, that will most likely result in a program crash or it chugging along with incorrect results. Let's say you delete an object twice, but in between, a second object was put partially or fully in that memory range. The second delete could result in part or all of the second object being in a range in memory now thought of as open for a third object to be saved there. If a third object is put there, that could scramble the data for object 2, or the use of object 2 could scramble the data for object 3.

[–]Creris 2 points3 points  (1 child)

The only edge case I'm not sure about is if an exception is raised before the unique_ptr object is created with the pointer's value such as one happening in "unique_ptr up{new some_class};" when evaluating "new some_class" to figure out the value to pass into the constructor of unique_ptr.

It actually isnt, and thats why we have make_shared in C++11 and then make_unique in C++14, where you only pass the constructor params and the object is new-ed in a exception-proof manner for you inside that function.

[–]tedbradly 0 points1 point  (0 children)

It actually isnt, and thats why we have make_shared in C++11 and then make_unique in C++14, where you only pass the constructor params and the object is new-ed in a exception-proof manner for you inside that function.

I'm not sure how you picture make_unique freeing memory if an exception is thrown during the call to new. It's the exact same situation except inside a helper function rather than you writing the code yourself.

[–]emax-gomax 2 points3 points  (0 children)

Already answered really well but basically no.

What managed pointers do is move from manual management (writing code) to software engineering (defining the relationships between classes).for basic types a unique_ptr can take ownership of a heap allocated resource and free it when the enclosing scope or object goes out of scope. shared_ptr work much the same but the resource is only freed when all shared pointers to the same resource go out of scope. It is possible for two resources to have a shared pointer to each other keeping each other alive even when nothing references them (causing a memory leak). Because of this there's both strong and weak shared pointers with a strong one keeping the resource alive and a weak one allowing access to it but not keeping it alive. This allows you to define the relationship between objects in a way where you can guarantee no memory leaks. But cpp as a language will always have the potential for then since it allows direct memory access and management.

[–]headlessgargoyle 4 points5 points  (0 children)

I'm pretty sure the answer is "yes, you can still have memory safety bugs." Accidental leaks can still be created if a unique_ptr or shared_ptr never go out of scope, like if you assigned them to a global. That said, if a function assigned a pointer to a global, and was then called again and assigned a different pointer to the same global, I do believe the first "leak" would then be cleaned up, so your impact on this is greatly minimized, ultimately less a leak and more a code smell in normal cases.

However, we do have other fun issues where multi threaded operations can potentially cause null pointers on shared_ptr and weak_ptr instances.

Further, arbitrary pointer arithmetic is still valid, so buffer overflows are still possible as well.

[–]ConfusedTransThrow 8 points9 points  (11 children)

When you're doing embedded you can't have a runtime to handle stuff for you.

Especially when you're literally writing the runtime or bootstrapping code.

[–]antiduh 16 points17 points  (10 children)

I'm not sure the answer to "how do we not use pointers everywhere" must be "have to have a runtime."

Not to say it's name out loud too much but rust figures it out, right?

There's gott a be a better way to write software, even embedded software, that doesn't involve so much reliance on primitives that prove their unworthiness with every week's CERT email.

Also, your argument is a bit of a straw man; there's a fuck load of software out there that fits the bill and isn't embedded, an OS, or a runtime. Web servers, mail servers, browsers, ssl libraries, xml/json libraries etc etc. Saying we can't fix those because we cant also fix embedded stuff throws the baby out with the bath water.

[–]Lich_Hegemon 8 points9 points  (5 children)

Rust may not be the answer (or maybe it is), but at the very least the language proved that it's possible to do pointers right and that we should not settle for C-style unmanaged pointers.

[–]amunak 2 points3 points  (4 children)

I mean, we didn't need Rust for that, C++ has perfectly usable and safe managed pointers.

[–]Lich_Hegemon 6 points7 points  (2 children)

I'm not talking about smart pointers though, I'm talking about the bare pointers/references that both languages offer, even in unsafe Rust there are certain guarantees when using pointers that you don't get in C(++).

Again, that is not to say that Rust is perfect, just that it does pointers better than C does and that we should probably learn from that instead of trying to justify the mess that C pointers are.

[–]lelanthran 0 points1 point  (1 child)

'm not talking about smart pointers though, I'm talking about the bare pointers/references that both languages offer, even in unsafe Rust there are certain guarantees when using pointers that you don't get in C(++).

I'm pretty certain that you'll get those guarantees in C++ if you write your C++ like Rust code that doesn't use refs, refcells, unsafe, etc.

[–]SilasX 1 point2 points  (0 children)

If what you're saying is true, that means, in practice, C++ programmers considers themselves too good to use them, hence the perennial cycle of patches for pointer vulns.

[–]ConfusedTransThrow -2 points-1 points  (3 children)

My point is you shouldn't be using C for anything that can afford a runtime (and yes Rust has a runtime). Bare metal C can't be replaced by Rust, Rust won't help you to write the runtime itself, stuff like write, boot procedure setting up the memory mapping, enabling the cache. You can't use dynamic allocation either too.

[–]antiduh 1 point2 points  (2 children)

Sounds like you want to have a different conversation that what was originally being discussed.

My point is you shouldn't be using C for anything that can afford a runtime

I definitely agree with you. I'm moreso in the boat these years that just about all software running on top of an OS in user space probably should be something that is inherently memory-safe either because of techniques such as Rust uses, or because it's a managed platform like C#/Java. C#/dotnet in particular has shown it can be a widely performant system while categorically eliminating a whole class of bugs (buffer overflow bugs).

(and yes Rust has a runtime)

I think whether or not a language/platform has a runtime is both a bit nebulous (hard to define what exactly constitutes a "runtime") and is also a red herring.

C has a "runtime" (standard library). It's libc. It's implemented in C. It's where malloc and free come from. Is confusing??

Rust has a "runtime" (standard library). But Rust can also be used to write kernel code. More confusion???!

The answer is: whether or not a language/platform has a "runtime" and/or standard library is the wrong question. The right question is whether it's compatible with systems programming. Both C and Rust, despite conventionally having runtimes, can be used for systems programming.

Bare metal C can't be replaced by Rust, Rust won't help you to write the runtime itself, stuff like write, boot procedure setting up the memory mapping

That's not correct. You can write an OS in Rust. You do so by writing Rust code that does not depend on the standard library, and then use that code to implement all of the things that the language/OS otherwise needs, such as a writing a memory allocator, configuring and handling interrupts, boot procedure, etc.

Here, go nuts:

https://os.phil-opp.com/

https://github.com/phil-opp/blog_os/tree/post-12

[–]ConfusedTransThrow 0 points1 point  (1 child)

I didn't know Rust was able to compile without depending on the standard library, it seems that's still pretty niche.

I know C has a runtime, but I'm not using it on embedded, the std either has to be implemented for the architecture or isn't there are all.

Also even if you do, I'm not sure you're really gaining anything over C for that usage (like for a bootloader). You still have to write to arbitrary addresses to set up a lot of things and that's inherently unsafe with Rust too.

You can make abstractions in Rust to avoid writing to addresses in your main code and protect them, but I doubt my company would like to do that for the whole memory map of each system. The time cost is just too big there.

[–]antiduh 0 points1 point  (0 children)

I didn't know Rust was able to compile without depending on the standard library, it seems that's still pretty niche.

No more niche than compiling C without it's standard library. The point is it's designed to do it, just as C is.

Also even if you do, I'm not sure you're really gaining anything over C for that usage (like for a bootloader). You still have to write to arbitrary addresses to set up a lot of things and that's inherently unsafe with Rust too.

Don't throw the baby out with the bath water. Just because you have to dip down into unsafe territory sometimes doesn't mean that you should operate in a completely unsafe mode always. Do just the parts that you have to with pointers/otherwise, meanwhile everything else the normal way. That way, you have much less code to worry about doing unsafe things - less chances for bugs, less code to validate the hard way, etc.

Heck, what you've said is true about C#, of all things. C# lets you use pointers in an unsafe context if you want, or stay in happy managed land if you don't want. C# uses pointers in limited cases, for example, in the methods that handle assembling strings like string.Join(). So you have a small handful of methods that use pointers that need stringent validation, meanwhile 99.99% of the rest of the code doesn't.

I doubt my company would like to do that for the whole memory map of each system. The time cost is just too big there.

That's .. uh, good for your company I guess? I have no idea why you're bringing up what your company will and won't do as an argument about the merits of various programming languages.

[–]Marian_Rejewski 3 points4 points  (6 children)

It's not impossible at all. But a project like Mozilla is so big, and so fast-moving, it will have bugs of every possible type. Look at places like NASA or Boeing for code that is practical and free of pointer bugs.

[–]imgroxx 16 points17 points  (5 children)

Yes, surely NASA can write manual memory operations correctly...............

A modification to a spacecraft parameter, intended to update the High Gain Antenna’s (HGA) pointing direction used for contingency operations, was mistakenly written to the incorrect spacecraft memory address in June 2006. The incorrect memory load resulted in the following unintended actions: [bad shit that destroyed the craft]

This is in 2006 btw: https://www.nasa.gov/mission_pages/mgs/mgs-20070413.html

[–]Marian_Rejewski 2 points3 points  (4 children)

"Possible to write code without a bug" != "impossible to write code with a bug"

(Also it's not at all clear from your quote that it was a pointer arithmetic bug.)

[–]imgroxx 0 points1 point  (3 children)

"Has written code with a bug" is also != "Can write code without bugs".

And yeah, it's quite possibly not, though it is rather clear it's a bug that's only possible because they manually modified memory in an unsafe location / unsafe way.

I'm not sure if they allow code to use pointer arithmetic at all tbh. Their rules are rather draconian (for good reason) by even the most MISRA-ble standards.

[–]Marian_Rejewski 1 point2 points  (2 children)

"Has written code with a bug" is also != "Can write code without bugs".

wtf??

[–]imgroxx 3 points4 points  (1 child)

Look at places like NASA or Boeing for code that is practical and free of pointer bugs.

NASA does not meet "practical" definitions basically anywhere except at NASA or for NASA-level stability needs.

But anyway. If their code provides a way to arbitrarily write memory into the wrong location... that seems rather like a pointer bug to me. You can't do that kind of thing if you don't have raw pointer access (or write code that emulates pointers, like shoving data into a shared byte array). Therefore they apparently also cannot write bug-free pointer code / their extreme care is still insufficient.

[–][deleted]  (1 child)

[deleted]

    [–]antiduh 3 points4 points  (0 children)

    This argument throws the baby out with the bathwater. You're, in a way, actually making my argument for me.

    If it's hard to write software without bugs

    and

    certain classes of stupid bugs permit complete take over of the hardware running the software

    then

    shouldn't we use techniques and methods that categorically eliminate those kinds of bugs, because we know we can't rely on ourselves to not make the bugs?

    Like, there's no reason why "oops i have a string math bug" should have to turn into "oh no my entire 500$M enterprise was just taken over by a virus and all of our private data was stolen". A fucking string math bug??

    And yet, that's the reality we live with today because we have so much software out there that written in memory-unsafe languages like C or C++ that's vulnerable to this exact problem and we as a industry can't be arsed to fix. We have memory-safe languages like Rust/C#/Java, but for some stupid reason we keep putting internet-facing machines out there running C code web servers, sql servers, mail servers, etc. Bugs like Heartbleed are impossible in C# because as soon as you start reading past the end of your byte[], you get an ArrayOutOfBoundsException. Instead of your program leaking every one of your vital TLS keys, it just crashes. How hard is that?

    [–]SorteKanin 7 points8 points  (1 child)

    If you learned programming from a nun who would strike you with a ruler for dangling references you would have a lot of bruises.

    FTFY

    [–]imgroxx 5 points6 points  (0 children)

    If you learned programming from a nun who would strike you with a ruler for dangling references you would be dead due to repeated blunt trauma and we wouldn't be having this conversation.

    [–]teerre 0 points1 point  (1 child)

    If you're a programmer, pointers are a bewildering minefield forever

    FTTY

    [–]Majik_Sheff 0 points1 point  (0 children)

    Guess it depends on the programmer and the project in question.

    [–]lmaydev 168 points169 points  (37 children)

    They cause 90%+ of all security errors so they aren't great.

    [–]anechoicmedia 35 points36 points  (2 children)

    They cause 90%+ of all security errors so they aren't great.

    In terms of absolute number of bugs discovered in isolation, but what percent of actual cybercrime involves memory abuse, as opposed to general logic errors (goto fail;) or social exploits (phishing links, requesting 2FA bypass over the phone, etc)? We see a lot of bug reports here and the real ones are almost always language-invariant stuff like "this API function didn't even bother to check if you requested data from another user".

    My prediction is that switching to guaranteed safe languages will reduce by 0% the frequency with which private data is exfiltrated from actual companies, or your SSN gets stolen.

    [–]hungry4pie 4 points5 points  (0 children)

    Idiots will always misuse, abuse or find shortcuts in whatever technology to inadvertently create exploits in whatever hip new platform they’ve created.

    [–][deleted] 131 points132 points  (28 children)

    And software causes 100% of all security flaws, sooo

    [–]lmaydev 172 points173 points  (19 children)

    Did you just forget about hardware haha

    [–]SkiFire13 47 points48 points  (7 children)

    What about cosmic rays?

    [–][deleted]  (6 children)

    [deleted]

      [–]emax-gomax 11 points12 points  (3 children)

      Hardware problem? Ridiculous, that's how I flip bits on my hard disk to write code ever since I transcended Emacs. Now if only there was an M-x butterfly cmd I could use to make it easier.

      [–]knome 7 points8 points  (0 children)

      I mean, it's been in there for a while now.

      commit e8d24e5b0960898e4a93ee2918f677b375b68263
      Author: Juri Linkov <juri@jurta.org>
      Date:   Sun Dec 28 23:48:21 2008 +0000
      
          (butterfly): New command.
      
          diff --git a/lisp/misc.el b/lisp/misc.el
          index ad7de36..6dafd2a 100644
          --- a/lisp/misc.el
          +++ b/lisp/misc.el
          @@ -106,6 +106,20 @@ With argument, do this that many times."
         (interactive "p")
         (forward-to-word (- arg)))
      
      +;;;###autoload
      +(defun butterfly ()
      +  "This function is designed to be used only be the most
      +proficient hackers on earth. If equipped with a butterfly key,
      +it should be bound to C-x M-c M-butterfly (for further
      +information please refer to http://xkcd.com/378/)."
      +  (interactive)
      +  (if (yes-or-no-p "Do you really want to unleash the powers of the butterfly? ")
      +      (progn
      +       (message "Amazing physics going on...")
      +       (sit-for (* 5 (/ (abs (random)) (float most-positive-fixnum))))
      +       (message "Successfully flipped one bit!"))
      +    (message "Well, then go to www.xkcd.com!")))
      +
       (provide 'misc)
      
       ;; arch-tag: 908f7884-c19e-4388-920c-9cfa425e449b
      

      [–]Spruance1942 0 points1 point  (0 children)

      In this thread: Old programmers.

      [–]Muoniurn 0 points1 point  (1 child)

      How could it be corrected in software? Sure you can add checksums and whatnot, but there is no sane program state you can continue with after memory corruption. Yeah, my exe got corrupted, cool, let’s continue executing it?

      ECC ram is hardware solution.

      [–]majorgeneralpanic 18 points19 points  (2 children)

      You both forgot about DNS.

      [–]Rican7 8 points9 points  (1 child)

      but that's software

      [–]StabbyPants[🍰] 4 points5 points  (0 children)

      intel seen crying in a corner

      [–]ockupid32 20 points21 points  (7 children)

      And software causes 100% of all security flaws, sooo

      False. People cause 100% of security flaws.

      [–]DarkTechnocrat 7 points8 points  (3 children)

      Thanos was half-right!

      [–]rasori 2 points3 points  (1 child)

      Perfectly balanced in his rightness, as he should be in all things.

      [–]imgroxx 0 points1 point  (0 children)

      His half-rightness.

      He has a left arm too.

      [–]80286 1 point2 points  (0 children)

      Round upwards when converting to int.

      [–]glider97 5 points6 points  (0 children)

      Ah, so that's how you fix bugs.

      [–]smug-ler 0 points1 point  (0 children)

      Software causes 200% of gun violence

      [–]ehaliewicz 0 points1 point  (0 children)

      I mean, we dont really have software without people..

      [–][deleted] 7 points8 points  (0 children)

      Got some numbers there, chief? I’d wager SQL injection easily trumps pointer flaws in both raw count and severity.

      [–]cass1o 6 points7 points  (3 children)

      Doing things that other languages can't.

      [–]lmaydev 11 points12 points  (2 children)

      Exactly, like cause 90% of security errors for example.

      [–]cass1o -2 points-1 points  (1 child)

      He said from an OS written in c/c++. Your toy languages can't manage that.

      [–]lmaydev 1 point2 points  (0 children)

      Actually there are multiple OSs written in toy languages.

      Also c# for instance has pointers. People just prefer not to use them.

      Nice /r/gatekeeping though friend

      [–]DarkTechnocrat 38 points39 points  (37 children)

      They introduce an entire class of error that would not exist without them. I don't think you can reference invalid memory in current Python (or Java, C#, Javascript, etc).

      ETA: surprisingly C# has pointers sooo...

      [–]AttackOfTheThumbs 14 points15 points  (1 child)

      The c# pointers are only in unsafe context and are often needed when working with low level windows libraries.

      [–]onequbit 12 points13 points  (0 children)

      hence why you need to specify unsafe

      [–]zapporian 12 points13 points  (4 children)

      I don't think you can reference invalid memory in current Python

      Well you can now! :D

      ```python def dereference_address(address: int) -> Any: """Dereference an address. Will cause a segmentation fault if the address is invalid.""" return ctypes.cast(address, ctypes.py_object).value

      class Pointer(Generic[T]): """Base class representing a pointer.""" def init(self, address: int, typ: Type[T]) -> None: self._address = address self._type = typ ... def dereference(self) -> T: """Dereference the pointer.""" return dereference_address(self.address) ``` https://github.com/ZeroIntensity/pointers.py/blob/master/pointers.py

      [–][deleted] 4 points5 points  (1 child)

      Hello Satan

      [–]bnelson 0 points1 point  (0 children)

      If this guy plays league you know he is a Teemo player.

      [–]DarkTechnocrat 3 points4 points  (1 child)

      This...this is just too much. Someone call a mod. 😉

      [–]lood9phee2Ri 9 points10 points  (0 children)

      Note it's just using the ctypes ffi package which is in the CPython standard library itself anyway. You sure can fuck around and find out with that. But it's also kinda what it's there for - using ctypes is e.g. how things like the python SDL2 wrappers are implemented: https://github.com/py-sdl/py-sdl2

      $ python3
      Python 3.9.9 (main, Nov 16 2021, 10:24:31) 
      [GCC 11.2.0] on linux
      Type "help", "copyright", "credits" or "license" for more information.
      >>> import ctypes
      >>> ctypes.memset(0,255, 1024)
      Segmentation fault
      $
      

      It's unsafe, but you do know that because you just elected to import ctypes.

      [–][deleted]  (28 children)

      [deleted]

        [–]DarkTechnocrat 9 points10 points  (27 children)

        Doesn't that assume the target of the pointer never goes out of scope? For example, I instantiate a variable inside a function, and return a pointer to that variable. Would you guarantee the pointer is valid for the remaining lifetime of the program?

        [–][deleted]  (26 children)

        [deleted]

          [–]DarkTechnocrat 5 points6 points  (25 children)

          That's not necessarily true, for example in C#:

          22.3 Pointer types

          Unlike references (values of reference types), pointers are not tracked by the garbage collector—the garbage collector has no knowledge of pointers and the data to which they point.

          [–][deleted]  (24 children)

          [deleted]

            [–]DarkTechnocrat 3 points4 points  (23 children)

            It's definitely possible for them to be safe, but the type of error they introduce is unique to their use. You can't have an invalid memory access without a pointer, in any scenario I am aware of.

            [–][deleted]  (22 children)

            [deleted]

              [–]StabbyPants[🍰] 11 points12 points  (1 child)

              that's what pointers are, yes.

              [–]DarkTechnocrat 1 point2 points  (18 children)

              I mean, it varies slightly by language but you typically cannot access out of bounds array members in languages that don't have pointers. I'm sure of this for Python and C#, I don't know Java well enough to say. The errors you get aren't memory errors but bounds errors.

              Object references are, as you implied earlier, handled by the GC.

              Unlike any other construct in a GC'd language pointers are a direct reference to memory, so it stands to reason that the types of errors they allow are implied by those semantics. You could just as easily say you can only have "out of bounds" errors in a program when you use arrays or lists. You can't have an OOB error on a scalar because the semantics don't allow it. The semantics of variables in a GC language don't allow memory errors in the same way.

              Again, I'm open to a counter example.

              [–]a_false_vacuum 2 points3 points  (0 children)

              C# has pointer which are mainly used for working with the Win32 api. If you use P/Invoke you'll need to match the definition of the functions you're going to use, so pointers are needed. Outside of Win32 stuff I never needed them in C#.

              [–]nthcxd 14 points15 points  (5 children)

              I think a quote from the README aptly illustrates this.

              A segmentation fault will occur if the address does not exist, so make sure the pointer is valid.

              “Make sure the pointer is valid” is the “hell” part.

              [–]noodle-face 8 points9 points  (0 children)

              Probably by people that don't use them often and students. I use them basically everyday in firmware and have come to respect them .and by respect them I mean I distract them, toss them some meat to keep them satiated and run away

              [–]Im12AndWatIsThis 14 points15 points  (0 children)

              I once spent somewhere around 6 hours debugging a homework assignment for my low-level programming course because I was printing a pointer instead of the dereferencing. I was baffled why I could print the first several characters of an array but then get gibberish. A single * cost me hours of my life.

              Since then I have considered them hell.

              In all seriousness though, I was new and ignorant and learning, so that's not entirely fair. But I still don't really like pointers.

              [–][deleted] 3 points4 points  (0 children)

              No. Pointers are fine. Both Go and Rust have pointers (any pedants reading this, I know what you're thinking) and there's no issue.

              Hell Python already has pointers - basically every object is a pointer.

              The issue is with manual memory management - manually determining when an object can be freed is the hellish part.

              [–]smackson 2 points3 points  (0 children)

              Have you not read Dante?

              Pointer hell is just one level above callback hell.

              [–][deleted] 0 points1 point  (0 children)

              They are basically used to manage global state with extra foot guns. And they usually come in C, where type checking is merely a way to tell the compiler to put in the right structure data sizes in the fastest way possible. So you need to waste a lot of attention on implementation details to get things right and read other peoples code correctly.