Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Shivahn
Posts: 2200
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: Coding: Fleeting Thoughts

Postby Shivahn » Wed May 16, 2012 11:39 pm UTC

I meant, when do you use a unique_ptr and weak_ptr and shared_ptr? I don't quite understand the differences in uses between the smart pointers

Sc4Freak wrote:Basically a general rule of thumb is to never say "new" without immediately putting the result into a smart pointer.

Code: Select all

{
   Foo* x = new Foo(); // bad
   /* ... */
   delete x; // have to call delete manually otherwise you'll leak
}

Code: Select all

{
   unique_ptr<Foo> x(new Foo()); // good
   /* ... */
} // x magically goes away!

Ok, cool. I have a question though. Is this acceptable?

Code: Select all

fun(Foo* x)
{
unique_ptr<Foo> point(x);
}

fun(new Foo());
?

It seems to me that unique_ptr should destroy x when it goes out of scope, but since x is being allocated in the function call, I'm not sure that I understand exactly what goes on, and would prefer to avoid memory leaks.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Thu May 17, 2012 1:03 am UTC

As their names imply, unique_ptr is for unique ownership and shared_ptr is for shared ownership.

Under the hood, unique_ptr automatically deletes the pointed-to-object when the unique_ptr goes out of scope. shared_ptr works differently - it only deletes the pointed-to-object if the last shared_ptr pointing to that object has gone. What that means is that you can copy shared_ptrs and pass them around freely and the pointed-to-object will simply be deleted once the last reference to it is gone. You can't do that with unique_ptr… think about what would happen if you had two unique_ptrs to the same object. Once one of the unique_ptrs is destroyed or goes out of scope, it'll automatically delete the pointed-to-object. But what about the other remaining unique_ptr? It's now pointing to an object that's been deleted - and that's bad. This is why unique_ptr prohibits copying but shared_ptr allows it.

shared_ptr uses reference counting to determine when to delete the object. Each new shared_ptr that points to an object will increment the reference count. Each time a shared_ptr is destroyed it decrements the reference count. When the refcount reaches 0, the object is destroyed (because it means the last reference to it went away).

Code: Select all

{
   unique_ptr<Foo> x(new Foo());
   // ...
} // the Foo that x points to is deleted here

Code: Select all

{
   shared_ptr<Foo> y(new Bar()); // create a new shared_ptr
                          // the reference count is 1 (only one shared_ptr to this object exists)

   {
      shared_ptr<Bar> z = y; // make a copy of the pointer
                        // the reference count is now 2
   } // z gets destroyed here, and it decrements the reference count to 1

   // y is still valid here, and so is the Bar it points to
   y->Frobnicate();
   
} // y is destroyed here, the refcount is decremented to 0, and the Bar is destroyed


Shivahn wrote:Ok, cool. I have a question though. Is this acceptable?

No. Never do that.

Inside fun, you have no clue where that pointer came from. What happens if I do this:

Code: Select all

Foo f;
fun(&f);


At the end of fun, unique_ptr will try to delete the object even though it wasn't created by "new". And your application will promptly explode.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Thu May 17, 2012 1:29 am UTC

Sc4Freak wrote:
Shivahn wrote:Ok, cool. I have a question though. Is this acceptable?

No. Never do that.

Just to clarify, it's not incorrect, just a bad idea, at least if those mean something different to you.

The fact that fun takes a normal pointer but then puts it into a unique_ptr is essentially the same as if it took the normal pointer and manually called delete. So let's just take that case.

The problem is that you've taken something which is very much part of the interface of a function ("I delete my parameter") and put it solely in the implementation and (hopefully) documentation. This means it's easy to make the sort of mistake that Sc4Freak points out, where you pass a pointer to something that can't be deleted. (The group I'm in has had a couple occurrences of similar bugs.)

Making the unique_ptr be what's actually passed as the parameter takes the interface fact "I delete my parameter" and actually promotes that to be part of the signature of the function -- which means the compiler can start to do checking for you.

It still won't prevent errors:

Code: Select all

Foo x;
fun(unique_ptr<Foo>(&x)); // bad doggy but the compiler will be happy

but it will tend to make them a lot more obvious. In the case of those two lines, I can tell you that there's an error without knowing anything about the implementation of fun.

Now, that's not to say you'll never write a function that takes a raw pointer and takes ownership of it eventually to delete it and have it be a good idea... it's theoretically possible. But... it won't be remotely common in C++.

User avatar
TheChewanater
Posts: 1279
Joined: Sat Aug 08, 2009 5:24 am UTC
Location: lol why am I still wearing a Santa suit?

Re: Coding: Fleeting Thoughts

Postby TheChewanater » Thu May 17, 2012 7:03 pm UTC

Sc4Freak wrote:Ok, cool. I have a question though. Is this acceptable?

Code: Select all

fun(Foo* x)
{
unique_ptr<Foo> point(x);
}

fun(new Foo());
?

It seems to me that unique_ptr should destroy x when it goes out of scope, but since x is being allocated in the function call, I'm not sure that I understand exactly what goes on, and would prefer to avoid memory leaks.


In this case, you could just have it stack-allocated.
ImageImage
http://internetometer.com/give/4279
No one can agree how to count how many types of people there are. You could ask two people and get 10 different answers.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Thu May 17, 2012 9:28 pm UTC

To be clear, people are saying that the "right" way to do it is:

Code: Select all

void fun(unique_ptr<Foo> point)
{
  // use point here
}

fun(unique_ptr<Foo>(new Foo()));

This exposes the fact that you'll be deleting whatever you pass in in the interface of the function 'fun'.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Thu May 17, 2012 9:51 pm UTC

So I learned today that the code base at work probably over-uses the async task model for things that aren't really IO bound, only that they do IO at all.

I like when less work is the correct answer. :mrgreen:

User avatar
Shivahn
Posts: 2200
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: Coding: Fleeting Thoughts

Postby Shivahn » Thu May 17, 2012 10:38 pm UTC

Ok, thanks everyone. I've changed all the functions to foo(boost::shared_ptr<Component> (new Component(<init>))). Though thinking about it, maybe I should go with unique_ptr instead, as when the pointer's destructor is called I'll always want to destroy the objects too.

I appreciate all the help. You guys are great.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Fri May 18, 2012 3:22 am UTC

shared_ptr has it's place. But that place is when you have complicated lifetime management, and/or you want to create "temporary" references stored somewhere else which "you are sure will last less time than the primary reference" (or, for which you don't know if they will last less time than the primary) --, ie "weak_ptr".

unique_ptr encapsulates the idea that "this variable owns this chunk of heap" in an efficient and easy to understand way. "shared_ptr" says "you cannot be certain what the lifetime of this chunk of heap is" -- which increases complexity.

(I sort of wish that I could have a unique_ptr + weak_ptr type pattern in the standard library. unique_ptr for whomever owns it, and weak_ptr (or something similar) for everything else. But I understand why not: you lock a weak_ptr by turning it into a shared_ptr, and such an operation makes no sense when your root is a unique_ptr...)
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Fri May 18, 2012 3:26 am UTC

What would a "unique_weak_ptr" actually accomplish though?

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Fri May 18, 2012 4:28 am UTC

Tell me when I would be referencing memory that has been deleted.

The two biggest memory errors are leaks and dangling pointers. Unique ptr solves leaks... I want to solve dangling as well.

Shared and weak has issues with leaks due to reference leaks.

Hmm. A weak unique that takes a lambda that takes a pointer? Naw that doesn't work well...
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Shivahn
Posts: 2200
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: Coding: Fleeting Thoughts

Postby Shivahn » Fri May 18, 2012 5:32 am UTC

Yakk wrote:unique_ptr encapsulates the idea that "this variable owns this chunk of heap" in an efficient and easy to understand way. "shared_ptr" says "you cannot be certain what the lifetime of this chunk of heap is" -- which increases complexity.

That's what I need. I originally just went with shared_ptr because there are going to be other references to the pointee, but then I realized that this particular reference is the one I'm going to want the pointee's existence based upon. So I'm gonna use unique pointers so that when the pointer is destroyed, it destroys the object (which will be responsible for cleaning references to itself out of other places. I'll have to be careful to implement that well.).

Also, sorry to have been using this thread as the "IT DOESN'T WORK" thread recently. I... sorta forgot it existed until just now. Then I went and wrote up a post in it and as I was writing it up, I realized the solution to my problem. Funny how an hour or two of debugging didn't help, and then writing a question about it forced me to look at it in a new way and it became glaringly obvious.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Fri May 18, 2012 4:10 pm UTC

Yakk wrote:Tell me when I would be referencing memory that has been deleted.

The two biggest memory errors are leaks and dangling pointers. Unique ptr solves leaks... I want to solve dangling as well.

Shared and weak has issues with leaks due to reference leaks.

Hmm. A weak unique that takes a lambda that takes a pointer? Naw that doesn't work well...

In that case it wouldn't be terribly difficult to implement this yourself, you'd just need a version of unique_ptr that also allocates a control block to keep track of weak references. It would also give unique_ptr a memory overhead not dissimilar to shared_ptr

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5101
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Fri May 18, 2012 4:36 pm UTC

Spoiler:

Code: Select all

private static string FirstWord(string sentance)
{
  if (sentance != null)
  {
    string[] delim = { CONST_COLONCOLON_ };
    string[] split = sentance.Split(delim, StringSplitOptions.None);
    if (split.Length != 0 && split[0] != null)
    {
       return split[0];
    }
    else
    {
       return null;
    }
  }
  else
  {
    return string.Empty;
  }
}

I cannot imagine what this code was originally supposed to do. Or why sentence is misspelled. Or why the return types for a failure chooses arbitrarily between nulls and empty strings. I mean, this thing doesn't even work on sentences, it works on IDs. And as far as I'm aware they have never included the string " :: ".

EDIT: Also a block of code that does:
Spoiler:

Code: Select all

if(condition1){
  if(condition2){
    //Do X
  }
  else{
    //Do X
  }
else{
  if(condition3){
    //Do X
  }
  else{
    //Do X
  }
}
Where X is several lines of duplicated code. The conditionals don't change any variables (just in case you thought this might be sane).

I'm glad I got a free-writ to basically hack this thing apart and fix it. :mrgreen:

EDIT 2: Oh, wait, no, it was worse than I first thought. X is duplicated 4 more times, because there's another if-else wrapped around the block I posted...

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Sat May 19, 2012 12:46 am UTC

I've often wished I could omit the parens from a generator expression when it's passed as sole arg to a function.

Turns out I could all along.

Code: Select all

word = ''.join(random.choice(alphabet) for i in range(N))


Am I the only one who didn't know this?

Oh well, goodbye and good riddance, double parens.

User avatar
PM 2Ring
Posts: 3713
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Coding: Fleeting Thoughts

Postby PM 2Ring » Sat May 19, 2012 5:32 am UTC

troyp wrote:I've often wished I could omit the parens from a generator expression when it's passed as sole arg to a function.

Turns out I could all along.

Code: Select all

word = ''.join(random.choice(alphabet) for i in range(N))


Am I the only one who didn't know this?

Maybe. :) I discovered it a little while ago when I accidentally left out the inner parens in a similar situation. FWIW, I only migrated to Python 2.6 fairly recently and I tend to forget about generator expressions and find myself using a list comprehension instead.

BTW, unless you're using Python 3, it's better to use xrange() than range() in the above code.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Sat May 19, 2012 11:18 pm UTC

I almost always use xrange, but in cases where there's only a few dozen items (which is meant to be the case above), it kind of seems..silly?

I don't know, maybe I should just use it all the time if I don't want to keep the list (just for consistency). I'm not sure if range has any advantage over xrange. I had a suspicion it may be slightly faster for small sequences, but I'm not sure if that's true (and it would hardly ever matter, anyway).
edit: actually, now I think about it, xrange should be faster even for small lists. Not sure why I had the impression range was faster.

edit2: okay, I'm going to use xrange for small sequences. I have decided my use of range was simply senseless conservatism, thinking I need a "reason" (however small) to use xrange, when really I should need a reason not to. (I'm not sure why I'm bothering to think about this when it will be moot with Py3 anyway.)

User avatar
Quantum Potatoid
Posts: 141
Joined: Mon Aug 06, 2007 1:15 am UTC
Location: May only be known if velocity isn't. Same rules apply with taste and texture.

Re: Coding: Fleeting Thoughts

Postby Quantum Potatoid » Sun May 20, 2012 6:46 am UTC

So, I've been taking to learning PHP in order to get my new website running.
I have come to conclude that the creators of PHP were very drunk when naming their functions.
It's as if they threw darts at a list of words vaguely related to what the function is supposed to do, then removed all of the vowels from them.
"There's nothing wrong with having voices in your head, it's when they leave you out of the conversation you have to worry"
Spoiler:
iThis Cheese is Burning Me!

User avatar
headprogrammingczar
Posts: 3072
Joined: Mon Oct 22, 2007 5:28 pm UTC
Location: Beaming you up

Re: Coding: Fleeting Thoughts

Postby headprogrammingczar » Sun May 20, 2012 12:04 pm UTC

Just wait until you hit the hexadecimal lexer bug, or see an exception without a stack frame, or get hit by the incorrect fixity of ?:, or try to use mktime(), or ...
<quintopia> You're not crazy. you're the goddamn headprogrammingspock!
<Weeks> You're the goddamn headprogrammingspock!
<Cheese> I love you

User avatar
Aaeriele
Posts: 2127
Joined: Tue Feb 23, 2010 3:30 am UTC
Location: San Francisco, CA

Re: Coding: Fleeting Thoughts

Postby Aaeriele » Sun May 20, 2012 5:35 pm UTC

Quantum Potatoid wrote:So, I've been taking to learning PHP in order to get my new website running.
I have come to conclude that the creators of PHP were very drunk when naming their functions.
It's as if they threw darts at a list of words vaguely related to what the function is supposed to do, then removed all of the vowels from them.


If you really want to do yourself a favor, only spend the minimum amount of time learning PHP to do whatever you need to do quickly; if you still want to do more stuff after that, start learning something like Python and a web framework like Pylons or Django.
Vaniver wrote:Harvard is a hedge fund that runs the most prestigious dating agency in the world, and incidentally employs famous scientists to do research.

afuzzyduck wrote:ITS MEANT TO BE FLUTTERSHY BUT I JUST SEE AAERIELE! CURSE YOU FORA!

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Sun May 20, 2012 6:57 pm UTC

Aaeriele wrote:
Quantum Potatoid wrote:So, I've been taking to learning PHP in order to get my new website running.
I have come to conclude that the creators of PHP were very drunk when naming their functions.
It's as if they threw darts at a list of words vaguely related to what the function is supposed to do, then removed all of the vowels from them.


If you really want to do yourself a favor, only spend the minimum amount of time learning PHP to do whatever you need to do quickly; if you still want to do more stuff after that, start learning something like Python and a web framework like Pylons or Django.

Oh, sure. Now you tell him.

User avatar
Steax
SecondTalon's Goon Squad
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Coding: Fleeting Thoughts

Postby Steax » Mon May 21, 2012 2:53 am UTC

Quantum Potatoid wrote:So, I've been taking to learning PHP in order to get my new website running.
I have come to conclude that the creators of PHP were very drunk when naming their functions.
It's as if they threw darts at a list of words vaguely related to what the function is supposed to do, then removed all of the vowels from them.


Try looking up the Flourish library. It was my lifesaver for PHP - it serves as a wrapper for commonly used PHP functionality, and sanifies cookies, sessions, requests and security features. It also has an elegant ORM implementation. It's been my go-to ever since I found it. It doesn't force you to use any particular structure, it's just a library of common functions.

Aaeriele wrote:
Quantum Potatoid wrote:So, I've been taking to learning PHP in order to get my new website running.
I have come to conclude that the creators of PHP were very drunk when naming their functions.
It's as if they threw darts at a list of words vaguely related to what the function is supposed to do, then removed all of the vowels from them.


If you really want to do yourself a favor, only spend the minimum amount of time learning PHP to do whatever you need to do quickly; if you still want to do more stuff after that, start learning something like Python and a web framework like Pylons or Django.


I'd have moved to other frameworks if only getting good hosting for them were easy. For small-ish websites that can't afford/don't need a virtual/dedicated server, I've still yet to find a good one.

--

Can anyone find any good performance information for Node JS? I've been learning it lately and preparing to move my more lightweight websites over there (with MongoDB, probably), but I'm still wondering how much a boost I'm getting for splitting my skillset. I am very fond of the socket functionality, though.
In Minecraft, I use the username Rirez.

User avatar
phlip
Restorer of Worlds
Posts: 7572
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Mon May 21, 2012 2:11 pm UTC

Sc4Freak wrote:
Yakk wrote:Tell me when I would be referencing memory that has been deleted.

The two biggest memory errors are leaks and dangling pointers. Unique ptr solves leaks... I want to solve dangling as well.

Shared and weak has issues with leaks due to reference leaks.

Hmm. A weak unique that takes a lambda that takes a pointer? Naw that doesn't work well...

In that case it wouldn't be terribly difficult to implement this yourself, you'd just need a version of unique_ptr that also allocates a control block to keep track of weak references. It would also give unique_ptr a memory overhead not dissimilar to shared_ptr

The main question though is: what do you do if you lock a weak_ptr, and then delete the unique_ptr it's referring to? If you just don't delete the underlying object until the weak_ptr's become unlocked, then your new pointer is semantically identical to shared_ptr. To keep the semantics that make unique_ptr different from shared_ptr, you still want to delete it immediately. But with the weak_ptr locked, you then immediately go into an error state. Sure, if you delete the object first, and then go to lock the weak_ptr afterward, then you can return an error sentinel or throw an exception (as the real weak_ptr::lock() and shared_ptr::shared_ptr(weak_ptr) do, respectively)... but when it happens in the other order, you're in a destructor... you can't return values, and you can't throw exceptions. The most you can do is set some flag, and check it when you access the locked pointer... but then the semantics of the weak pointer get really messy. That means every access of the weak pointer needs to be checked, and have appropriate try/catch wrappings, even after you lock it. Indeed, locking would serve no purpose, and you may as well throw an operator* directly onto the weak_ptr, that checks every time.

I just think you'd have trouble making semantics for it that were (a) reasonably usable, and (b) still protects you from dangling pointers in any meaningful way.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Mon May 21, 2012 2:26 pm UTC

Or you could set the weak_ptr to null. Sure, technically that'd be undefined behavior, but practically speaking it's a hell of a lot more well-defined than accessing a dangling pointer...

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Mon May 21, 2012 4:01 pm UTC

No, setting it to nullptr is not a viable solution.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Aaeriele
Posts: 2127
Joined: Tue Feb 23, 2010 3:30 am UTC
Location: San Francisco, CA

Re: Coding: Fleeting Thoughts

Postby Aaeriele » Mon May 21, 2012 4:17 pm UTC

Steax wrote:
Aaeriele wrote:
Quantum Potatoid wrote:So, I've been taking to learning PHP in order to get my new website running.
I have come to conclude that the creators of PHP were very drunk when naming their functions.
It's as if they threw darts at a list of words vaguely related to what the function is supposed to do, then removed all of the vowels from them.


If you really want to do yourself a favor, only spend the minimum amount of time learning PHP to do whatever you need to do quickly; if you still want to do more stuff after that, start learning something like Python and a web framework like Pylons or Django.


I'd have moved to other frameworks if only getting good hosting for them were easy. For small-ish websites that can't afford/don't need a virtual/dedicated server, I've still yet to find a good one.


Heroku is one reasonable option. Their free tier works fine for "small-ish" websites.
Vaniver wrote:Harvard is a hedge fund that runs the most prestigious dating agency in the world, and incidentally employs famous scientists to do research.

afuzzyduck wrote:ITS MEANT TO BE FLUTTERSHY BUT I JUST SEE AAERIELE! CURSE YOU FORA!

User avatar
Steax
SecondTalon's Goon Squad
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Coding: Fleeting Thoughts

Postby Steax » Mon May 21, 2012 4:55 pm UTC

Really? I didn't know that. What does this free tier provide? I looked at it a while back - I didn't think there was a free one, and a single instance of each bare minimum matched that of a virtual server on other hosts.
In Minecraft, I use the username Rirez.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Mon May 21, 2012 5:00 pm UTC

Yakk wrote:No, setting it to nullptr is not a viable solution.

Personally I'd take it. It's better than accessing the dangling pointer.

But if you disagree, then you could still avoid a per-access check if you set it to an address of some other unmapped page and catch address exceptions so you can "rethrow" them as C++ exceptions. Might need some work to make it interoperate well with people who register their own SIGSEGV handlers and whatnot, but it definitely seems like a workable solution to me, at least on Linux. (On Windows I'm having trouble coming up with a mechanism that doesn't keep registering and unregistering SEH frames.)

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Mon May 21, 2012 5:16 pm UTC

phlip wrote:
Sc4Freak wrote:
Yakk wrote:Tell me when I would be referencing memory that has been deleted.

The two biggest memory errors are leaks and dangling pointers. Unique ptr solves leaks... I want to solve dangling as well.

Shared and weak has issues with leaks due to reference leaks.

Hmm. A weak unique that takes a lambda that takes a pointer? Naw that doesn't work well...

In that case it wouldn't be terribly difficult to implement this yourself, you'd just need a version of unique_ptr that also allocates a control block to keep track of weak references. It would also give unique_ptr a memory overhead not dissimilar to shared_ptr

The main question though is: what do you do if you lock a weak_ptr, and then delete the unique_ptr it's referring to? If you just don't delete the underlying object until the weak_ptr's become unlocked, then your new pointer is semantically identical to shared_ptr. To keep the semantics that make unique_ptr different from shared_ptr, you still want to delete it immediately.


Not really, the semantics aren't any different to traditional unqiue_ptr. When the unique_ptr is destroyed, the pointed-to object is destroyed as well. But the control block allocated on unique_ptr's construction is not freed until the last weak_ptr is destroyed.

When you construct a shared_ptr, it also allocates a control block to store refcounts - both strong (for shared_ptr's) and weak (for weak_ptr's). When the last shared_ptr is destroyed, the pointed-to-object is destroyed, but the control block containing the refcounts isn't destroyed until both the last weak_ptr and shared_ptr to it are released. A kind of "weak_ptr" for unique_ptr would work the same way except it wouldn't store a strong refcount, only a weak refcount. It doesn't change the semantics of unique_ptr any - you still use it as you always have. It just incurs a slightly higher memory overhead which I mentioned in my previous post, but that's an implementation detail.

User avatar
Aaeriele
Posts: 2127
Joined: Tue Feb 23, 2010 3:30 am UTC
Location: San Francisco, CA

Re: Coding: Fleeting Thoughts

Postby Aaeriele » Mon May 21, 2012 5:23 pm UTC

Steax wrote:Really? I didn't know that. What does this free tier provide? I looked at it a while back - I didn't think there was a free one, and a single instance of each bare minimum matched that of a virtual server on other hosts.


http://www.heroku.com/pricing#1-0

Notice the free 750 instance hours (which is basically a single web dyno) adjustment.
Vaniver wrote:Harvard is a hedge fund that runs the most prestigious dating agency in the world, and incidentally employs famous scientists to do research.

afuzzyduck wrote:ITS MEANT TO BE FLUTTERSHY BUT I JUST SEE AAERIELE! CURSE YOU FORA!

User avatar
Anubis
Posts: 222
Joined: Sun Mar 01, 2009 7:59 am UTC

Re: Coding: Fleeting Thoughts

Postby Anubis » Tue May 22, 2012 4:34 am UTC

Python is so much fun! I just started learning it today. I've been going through Project Euler problems, building a library of (what seem to me like) relatively efficient utilities as I go, and I can't remember the last time I enjoyed coding this much.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Tue May 22, 2012 12:44 pm UTC

Sc4Freak wrote:
phlip wrote:The main question though is: what do you do if you lock a weak_ptr, and then delete the unique_ptr it's referring to? If you just don't delete the underlying object until the weak_ptr's become unlocked, then your new pointer is semantically identical to shared_ptr. To keep the semantics that make unique_ptr different from shared_ptr, you still want to delete it immediately.


Not really, the semantics aren't any different to traditional unqiue_ptr. When the unique_ptr is destroyed, the pointed-to object is destroyed as well. But the control block allocated on unique_ptr's construction is not freed until the last weak_ptr is destroyed.

When you construct a shared_ptr, it also allocates a control block to store refcounts - both strong (for shared_ptr's) and weak (for weak_ptr's). When the last shared_ptr is destroyed, the pointed-to-object is destroyed, but the control block containing the refcounts isn't destroyed until both the last weak_ptr and shared_ptr to it are released. A kind of "weak_ptr" for unique_ptr would work the same way except it wouldn't store a strong refcount, only a weak refcount. It doesn't change the semantics of unique_ptr any - you still use it as you always have. It just incurs a slightly higher memory overhead which I mentioned in my previous post, but that's an implementation detail.
Except, of course, what you are describing is pretty much useless. You cannot use those weak_ptr for anything except "is the unique pointer destroyed or not".

The fact that weak_ptrs return shared_ptr is an implementation detail on lock -- the use case of weak_ptr is the ability to conditionally run code that only runs if the weak_ptr is valid for the entire length of code. With a shared_ptr weak_ptr, they implement this by producing a shared_ptr from the weak_ptr on demand.

Pulling this off with a unique_ptr is not all that possible.

In a language with complete rollbacks, one could imagine passing in a block of code that would be conditionally executed iff for the entire duration of the execution the weak_ptr remained valid. If not, one of two errors (unique_ptr destroyed in other context, unique_ptr destroyed "as a consequence of" the block of code) would be returned. Doing so in a realistic execution context outside of seriously constrained languages is much harder.

The best I can think of would be to give unique_ptr the entire shared_ptr semantics, but allow the weak_unique_ptr to be passed a code block where it gets a weak_unique_ptr_instance that can extend the life of the unique_ptr, but only so long as the block runs -- ie, a highly limited version of a shared_ptr. At this point, however, we are going to have all of the overhead of a shared_ptr -- all we get out of this is some hard to enforce statically demands upon the programmer. So the value is questionable.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Tue May 22, 2012 10:18 pm UTC

I think there are two different sets of semantics we're talking about here.

One is the shared_ptr semantics, where locking a weak_ptr extends the lifetime of the object until the code block has completed execution. As I think you already realize, that's self-contradictory when applied to unique_ptr. If you've taken control of the unique_ptr via a weak_ptr and forced an extension of the object's lifetime, then unique_ptr isn't unique. If this is your goal then the furthest you can get (while keeping unique_ptrs unique) is what I described previously - which as you mentioned is not terribly useful because it only lets you query whether the object is alive or dead.

The second set of semantics is where the block of code executes iff the lifetime of the pointed-to-object exceeds the duration of execution of the code block. This one doesn't seem too difficult to implement... if we make some huge, glaring assumptions first. Simply discard the use of weak_ptr::lock(), allow users to dereference weak_ptr directly, and have it throw an exception if the pointed-to object has died. If the calling code provides the strong exception guarantee (don't laugh) then program state will be reset to the point before the code block is executed.

Of course, practically speaking, that's just as useless because consistently providing the strong exception guarantee is near-impossible. :P

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed May 23, 2012 2:00 am UTC

Even throwing when you dereference isn't good enough.

You do a weak_ptr->foo(), and when you dereference you are good, but while running foo() the pointer was deleted.

(I ran into that ... issue ... when I was rolling my own smart pointer. In my case, it was between the dereference of the "local" smart pointer and the call to "addref" on the tooled data that did me in once in a blue moon.)
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Steax
SecondTalon's Goon Squad
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Coding: Fleeting Thoughts

Postby Steax » Thu May 24, 2012 12:30 am UTC

Today's overheard in the code:

Code: Select all

// key generation
do {
   // lets be honest with ourselves. The possibility of a collision between
   // two 128-character alphanumeric strings would require something like
   // 10^200 generations. We're building for 10 people on average. 20 tops.
   // Higher chances exist of the world just miraculously exploding for
   // no reason what-so-ever. Still, best be safe. We'd want to survive the
   // apocalypse. That'd look great on our portfolio.
   $key = fCryptography::randomString(128);
} while (fooUserKeyExists($key));
In Minecraft, I use the username Rirez.

User avatar
Dason
Posts: 1311
Joined: Wed Dec 02, 2009 7:06 am UTC
Location: ~/

Re: Coding: Fleeting Thoughts

Postby Dason » Thu May 24, 2012 12:36 am UTC

You have an opportunity for one helluva necro: viewtopic.php?f=11&t=11935&start=560
double epsilon = -.0000001;

User avatar
Shivahn
Posts: 2200
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: Coding: Fleeting Thoughts

Postby Shivahn » Thu May 24, 2012 11:07 pm UTC

It's sort of weird that people say computers think in 1s and 0s. It seems kind of like saying that English script is just straight lines and quarter-circles - sure, you can take a letter and break it into those, but nothing is really handled at that level, letters are really atomic. Computers are the same way, though - they don't really handle anything less than a byte at once. You have to do a lot of work to cover up the rest of the parts of a byte-sized "letter". So really, they think in base 256, at least those who use bytes as fundamental units.

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6579
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Fri May 25, 2012 12:00 am UTC

Well, base 8 bits is really just the most granular unit most computers can address. The electrical signals themselves we use to represent two possible states (which we usually call 0 and 1, which makes sense for many, but not all, operations). But really, they don't think at all; they just process instructions and numbers.
Summum ius, summa iniuria.

User avatar
Shivahn
Posts: 2200
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: Coding: Fleeting Thoughts

Postby Shivahn » Fri May 25, 2012 12:25 am UTC

Don't we all? :P

That's kind of what I'm saying though, the most granular thing in English is the letter, but they're all represented by just a few strokes. The pattern in them is what matters. Similarly, computers tend to operate on chunks of bits, rather than bits themselves, especially at higher levels.

Edit for a bit more clarity:

The meaning behind an individual bit depends on its location. A 1 in the second place is very different from a 1 in the first. You can't really treat them the same way, they're fundamentally different (for example, AND 1 will do different things to them). A byte is made up of bits, which you could say have the meaning of "on" or "off" (or 1 or 0), but they're really not the entities upon which computers operate - even bitwise operations, as I understand them, operate on the whole byte, they just do it in a bitwise fashion.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Fri May 25, 2012 2:04 am UTC

Computers think in voltages. :-)

Shivahn wrote:The meaning behind an individual bit depends on its location. A 1 in the second place is very different from a 1 in the first.

But really, you can extend this argument: the meaning of a byte depends on its location too. A 1 in the least-significant byte is different from a 1 in the most-significant; just like 'and 1' will return different results for the bits, so will it for bytes.

Really, most instructions operate on word level, not byte level, so base 4 billion-whatever for a 32-bit machine (or one in 32-bit mode, like x86). I'm pretty sure your typical RISC architecture (thinking of MIPS specifically) doesn't even have a way of operating on individual bytes, except for the lb and sb instructions.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Fri May 25, 2012 2:29 am UTC

Shivahn wrote:Don't we all? :P

That's kind of what I'm saying though, the most granular thing in English is the letter, but they're all represented by just a few strokes. The pattern in them is what matters. Similarly, computers tend to operate on chunks of bits, rather than bits themselves, especially at higher levels.

Edit for a bit more clarity:

The meaning behind an individual bit depends on its location. A 1 in the second place is very different from a 1 in the first. You can't really treat them the same way, they're fundamentally different (for example, AND 1 will do different things to them). A byte is made up of bits, which you could say have the meaning of "on" or "off" (or 1 or 0), but they're really not the entities upon which computers operate - even bitwise operations, as I understand them, operate on the whole byte, they just do it in a bitwise fashion.

I think saying computers "think in 1's and 0's" is fair, actually. That's the smallest unit that the computer can operate on. For instance, when you program, you can access each individual bit in a file. You can't get at any finer representation, like the actual electric potential state.

If you are lucky enough to work with a language that has good bitstream processing capabilities, then as the programmer you actually can deal with individual bits. And why not? It doesn't matter that the actual representation might not be bytes (in signal processing, you often deal with symbols that can attain a number of states that is not a power of two), but by the time it reaches the processor, it's bits.


Return to “Coding”

Who is online

Users browsing this forum: Link and 10 guests