Why are std::begin and std::end “not memory safe”?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







52















In this blog post, Eric Niebler states that:




What is wrong with std::begin and std::end? Surprise! they are not
memory safe. Consider what this code does:



extern std::vector<int> get_data();
auto it = std::begin(get_data());
int i = *it; // BOOM


std::begin has two overloads for const and non-const lvalues. Trouble
is, rvalues bind to const lvalue references, leading to the dangling
iterator it above.




I'm having trouble understanding his point and why it is a dangling reference.
Could someone explain?










share|improve this question




















  • 17





    How is the above code any different from auto it = get_data().begin();. That code has the same problem I think, so what point is the author is making?

    – john
    Feb 11 at 7:56






  • 10





    @john Eric is saying that ranges::begin is better than std::begin, he isn't claiming anything about .begin.

    – Marc Glisse
    Feb 11 at 8:58








  • 3





    @MarcGlisse OK, I was misled by the title of this post, and I couldn't easily find the original quote.

    – john
    Feb 11 at 9:00











  • Related question: stackoverflow.com/questions/48976859/…

    – Arne Vogel
    Feb 11 at 12:26






  • 2





    Personally, I would say that's more a combination of "not Machiavelli-safe" or "not derp-safe" and a quirk of rvalue references than "not memory-safe", since it demonstrates that std::begin() is exactly as memory-safe as the parameter you pass to it, and not inherently unsafe solely in and of itself. That's just me, though.

    – Justin Time
    Feb 12 at 7:40


















52















In this blog post, Eric Niebler states that:




What is wrong with std::begin and std::end? Surprise! they are not
memory safe. Consider what this code does:



extern std::vector<int> get_data();
auto it = std::begin(get_data());
int i = *it; // BOOM


std::begin has two overloads for const and non-const lvalues. Trouble
is, rvalues bind to const lvalue references, leading to the dangling
iterator it above.




I'm having trouble understanding his point and why it is a dangling reference.
Could someone explain?










share|improve this question




















  • 17





    How is the above code any different from auto it = get_data().begin();. That code has the same problem I think, so what point is the author is making?

    – john
    Feb 11 at 7:56






  • 10





    @john Eric is saying that ranges::begin is better than std::begin, he isn't claiming anything about .begin.

    – Marc Glisse
    Feb 11 at 8:58








  • 3





    @MarcGlisse OK, I was misled by the title of this post, and I couldn't easily find the original quote.

    – john
    Feb 11 at 9:00











  • Related question: stackoverflow.com/questions/48976859/…

    – Arne Vogel
    Feb 11 at 12:26






  • 2





    Personally, I would say that's more a combination of "not Machiavelli-safe" or "not derp-safe" and a quirk of rvalue references than "not memory-safe", since it demonstrates that std::begin() is exactly as memory-safe as the parameter you pass to it, and not inherently unsafe solely in and of itself. That's just me, though.

    – Justin Time
    Feb 12 at 7:40














52












52








52


5






In this blog post, Eric Niebler states that:




What is wrong with std::begin and std::end? Surprise! they are not
memory safe. Consider what this code does:



extern std::vector<int> get_data();
auto it = std::begin(get_data());
int i = *it; // BOOM


std::begin has two overloads for const and non-const lvalues. Trouble
is, rvalues bind to const lvalue references, leading to the dangling
iterator it above.




I'm having trouble understanding his point and why it is a dangling reference.
Could someone explain?










share|improve this question
















In this blog post, Eric Niebler states that:




What is wrong with std::begin and std::end? Surprise! they are not
memory safe. Consider what this code does:



extern std::vector<int> get_data();
auto it = std::begin(get_data());
int i = *it; // BOOM


std::begin has two overloads for const and non-const lvalues. Trouble
is, rvalues bind to const lvalue references, leading to the dangling
iterator it above.




I'm having trouble understanding his point and why it is a dangling reference.
Could someone explain?







c++ c++11 iterator std






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 11 at 17:51









Cody Gray

196k35385475




196k35385475










asked Feb 11 at 7:33









DavidbrczDavidbrcz

1,5681119




1,5681119








  • 17





    How is the above code any different from auto it = get_data().begin();. That code has the same problem I think, so what point is the author is making?

    – john
    Feb 11 at 7:56






  • 10





    @john Eric is saying that ranges::begin is better than std::begin, he isn't claiming anything about .begin.

    – Marc Glisse
    Feb 11 at 8:58








  • 3





    @MarcGlisse OK, I was misled by the title of this post, and I couldn't easily find the original quote.

    – john
    Feb 11 at 9:00











  • Related question: stackoverflow.com/questions/48976859/…

    – Arne Vogel
    Feb 11 at 12:26






  • 2





    Personally, I would say that's more a combination of "not Machiavelli-safe" or "not derp-safe" and a quirk of rvalue references than "not memory-safe", since it demonstrates that std::begin() is exactly as memory-safe as the parameter you pass to it, and not inherently unsafe solely in and of itself. That's just me, though.

    – Justin Time
    Feb 12 at 7:40














  • 17





    How is the above code any different from auto it = get_data().begin();. That code has the same problem I think, so what point is the author is making?

    – john
    Feb 11 at 7:56






  • 10





    @john Eric is saying that ranges::begin is better than std::begin, he isn't claiming anything about .begin.

    – Marc Glisse
    Feb 11 at 8:58








  • 3





    @MarcGlisse OK, I was misled by the title of this post, and I couldn't easily find the original quote.

    – john
    Feb 11 at 9:00











  • Related question: stackoverflow.com/questions/48976859/…

    – Arne Vogel
    Feb 11 at 12:26






  • 2





    Personally, I would say that's more a combination of "not Machiavelli-safe" or "not derp-safe" and a quirk of rvalue references than "not memory-safe", since it demonstrates that std::begin() is exactly as memory-safe as the parameter you pass to it, and not inherently unsafe solely in and of itself. That's just me, though.

    – Justin Time
    Feb 12 at 7:40








17




17





How is the above code any different from auto it = get_data().begin();. That code has the same problem I think, so what point is the author is making?

– john
Feb 11 at 7:56





How is the above code any different from auto it = get_data().begin();. That code has the same problem I think, so what point is the author is making?

– john
Feb 11 at 7:56




10




10





@john Eric is saying that ranges::begin is better than std::begin, he isn't claiming anything about .begin.

– Marc Glisse
Feb 11 at 8:58







@john Eric is saying that ranges::begin is better than std::begin, he isn't claiming anything about .begin.

– Marc Glisse
Feb 11 at 8:58






3




3





@MarcGlisse OK, I was misled by the title of this post, and I couldn't easily find the original quote.

– john
Feb 11 at 9:00





@MarcGlisse OK, I was misled by the title of this post, and I couldn't easily find the original quote.

– john
Feb 11 at 9:00













Related question: stackoverflow.com/questions/48976859/…

– Arne Vogel
Feb 11 at 12:26





Related question: stackoverflow.com/questions/48976859/…

– Arne Vogel
Feb 11 at 12:26




2




2





Personally, I would say that's more a combination of "not Machiavelli-safe" or "not derp-safe" and a quirk of rvalue references than "not memory-safe", since it demonstrates that std::begin() is exactly as memory-safe as the parameter you pass to it, and not inherently unsafe solely in and of itself. That's just me, though.

– Justin Time
Feb 12 at 7:40





Personally, I would say that's more a combination of "not Machiavelli-safe" or "not derp-safe" and a quirk of rvalue references than "not memory-safe", since it demonstrates that std::begin() is exactly as memory-safe as the parameter you pass to it, and not inherently unsafe solely in and of itself. That's just me, though.

– Justin Time
Feb 12 at 7:40












6 Answers
6






active

oldest

votes


















57














The get_data function returns an object. When used the way shown, that object will be a temporary object, which will be destructed once the full expression ends. The iterator now references a vector object which no longer exists, and can't be dereferenced or used in any useful way.






share|improve this answer



















  • 16





    Though this is definitely correct, isn't john's comment to the original post also appropriate? How does the given example show a problem of std::begin and std::end?

    – Benjamin Bihler
    Feb 11 at 8:35






  • 18





    Because std::begin lets you make that mistake, but std::ranges::begin will not.

    – Eric Niebler
    Feb 11 at 16:17



















51














I think Eric's point about std::begin is that it silently accepts an rvalue container as an argument to begin with. On the face of it, the problem with the code is also exemplified in



auto it = get_data().begin();


But std::begin is a free function template, it can be made to reject rvalues without needing to add the proper reference qualifiers to each container's begin members. By "just" forwarding it misses an opportunity to add a layer of memory safety to code.



Ideally, the overload set could have benefited from the addition of



template< class C > 
void begin( C&& ) = delete;


That one would have caused the code in the blog post to be flat out rejected on the spot.






share|improve this answer





















  • 1





    Is it possible for us to make a warning of deprecation or usage for that particular template instantiation instead of outright deleting it? Compiler specific extensions allowed.

    – Paul Stelian
    Feb 11 at 9:51






  • 4





    @PaulStelian - Here's how btw, pure C++14. coliru.stacked-crooked.com/a/7c99059b5b1a8dca

    – StoryTeller
    Feb 11 at 10:01






  • 3





    @PaulStelian - No, we can't. I intentionally provided an example in another namespace. To add this overload, we'd need to write a proposal, then get it voted int o the standard.

    – StoryTeller
    Feb 11 at 11:25






  • 3





    The thing is, as Alexandrescu points it out with humour in its 2018 cppcon talk, the C++ committee likes to be consistent in its past errors. One might think the reason why std::begin accepts r-values is to let begin(c) and c.begin() be perfectly equivalent. (but yes obviously this overload set would be ideal)

    – YSC
    Feb 11 at 12:24








  • 3





    @YSC .begin() could also be made to reject rvalues, couldn't it? iterator begin() && = delete;

    – The Vee
    Feb 11 at 18:00





















13














The temporary vector returned by get_data goes out of scope after std::begin is done. It is not kept alive, so it is an iterator into a destroyed object.






share|improve this answer































    4














    Is it fair to say this is a memory safety failing of std::begin?
    There is no 'safe' way of creating an iterator such that it will be valid to follow the pointer after the container is deleted.



    It lacks a check that another method has, but it's not like there is no way to make a ranges derived iterator go pop. You just have to try a bit harder...






    share|improve this answer































      2














      Because it allows initialisation from an rvalue, which is bad.






      share|improve this answer































        0














        in fact , the complicated function can be simplified to two short functions , such as



        int& foo(int x){
        return x;
        }
        int generate_a_int(){
        return 42;
        }


        and then invoke it foo(generate_a_int()), a temporary value is generated , once out of the function body, the temporary value generated by generate_a_int() is destroy , and then dangle reference is happened ...



        do you understand now?






        share|improve this answer
























          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54625792%2fwhy-are-stdbegin-and-stdend-not-memory-safe%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          6 Answers
          6






          active

          oldest

          votes








          6 Answers
          6






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          57














          The get_data function returns an object. When used the way shown, that object will be a temporary object, which will be destructed once the full expression ends. The iterator now references a vector object which no longer exists, and can't be dereferenced or used in any useful way.






          share|improve this answer



















          • 16





            Though this is definitely correct, isn't john's comment to the original post also appropriate? How does the given example show a problem of std::begin and std::end?

            – Benjamin Bihler
            Feb 11 at 8:35






          • 18





            Because std::begin lets you make that mistake, but std::ranges::begin will not.

            – Eric Niebler
            Feb 11 at 16:17
















          57














          The get_data function returns an object. When used the way shown, that object will be a temporary object, which will be destructed once the full expression ends. The iterator now references a vector object which no longer exists, and can't be dereferenced or used in any useful way.






          share|improve this answer



















          • 16





            Though this is definitely correct, isn't john's comment to the original post also appropriate? How does the given example show a problem of std::begin and std::end?

            – Benjamin Bihler
            Feb 11 at 8:35






          • 18





            Because std::begin lets you make that mistake, but std::ranges::begin will not.

            – Eric Niebler
            Feb 11 at 16:17














          57












          57








          57







          The get_data function returns an object. When used the way shown, that object will be a temporary object, which will be destructed once the full expression ends. The iterator now references a vector object which no longer exists, and can't be dereferenced or used in any useful way.






          share|improve this answer













          The get_data function returns an object. When used the way shown, that object will be a temporary object, which will be destructed once the full expression ends. The iterator now references a vector object which no longer exists, and can't be dereferenced or used in any useful way.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Feb 11 at 7:37









          Some programmer dudeSome programmer dude

          305k25265427




          305k25265427








          • 16





            Though this is definitely correct, isn't john's comment to the original post also appropriate? How does the given example show a problem of std::begin and std::end?

            – Benjamin Bihler
            Feb 11 at 8:35






          • 18





            Because std::begin lets you make that mistake, but std::ranges::begin will not.

            – Eric Niebler
            Feb 11 at 16:17














          • 16





            Though this is definitely correct, isn't john's comment to the original post also appropriate? How does the given example show a problem of std::begin and std::end?

            – Benjamin Bihler
            Feb 11 at 8:35






          • 18





            Because std::begin lets you make that mistake, but std::ranges::begin will not.

            – Eric Niebler
            Feb 11 at 16:17








          16




          16





          Though this is definitely correct, isn't john's comment to the original post also appropriate? How does the given example show a problem of std::begin and std::end?

          – Benjamin Bihler
          Feb 11 at 8:35





          Though this is definitely correct, isn't john's comment to the original post also appropriate? How does the given example show a problem of std::begin and std::end?

          – Benjamin Bihler
          Feb 11 at 8:35




          18




          18





          Because std::begin lets you make that mistake, but std::ranges::begin will not.

          – Eric Niebler
          Feb 11 at 16:17





          Because std::begin lets you make that mistake, but std::ranges::begin will not.

          – Eric Niebler
          Feb 11 at 16:17













          51














          I think Eric's point about std::begin is that it silently accepts an rvalue container as an argument to begin with. On the face of it, the problem with the code is also exemplified in



          auto it = get_data().begin();


          But std::begin is a free function template, it can be made to reject rvalues without needing to add the proper reference qualifiers to each container's begin members. By "just" forwarding it misses an opportunity to add a layer of memory safety to code.



          Ideally, the overload set could have benefited from the addition of



          template< class C > 
          void begin( C&& ) = delete;


          That one would have caused the code in the blog post to be flat out rejected on the spot.






          share|improve this answer





















          • 1





            Is it possible for us to make a warning of deprecation or usage for that particular template instantiation instead of outright deleting it? Compiler specific extensions allowed.

            – Paul Stelian
            Feb 11 at 9:51






          • 4





            @PaulStelian - Here's how btw, pure C++14. coliru.stacked-crooked.com/a/7c99059b5b1a8dca

            – StoryTeller
            Feb 11 at 10:01






          • 3





            @PaulStelian - No, we can't. I intentionally provided an example in another namespace. To add this overload, we'd need to write a proposal, then get it voted int o the standard.

            – StoryTeller
            Feb 11 at 11:25






          • 3





            The thing is, as Alexandrescu points it out with humour in its 2018 cppcon talk, the C++ committee likes to be consistent in its past errors. One might think the reason why std::begin accepts r-values is to let begin(c) and c.begin() be perfectly equivalent. (but yes obviously this overload set would be ideal)

            – YSC
            Feb 11 at 12:24








          • 3





            @YSC .begin() could also be made to reject rvalues, couldn't it? iterator begin() && = delete;

            – The Vee
            Feb 11 at 18:00


















          51














          I think Eric's point about std::begin is that it silently accepts an rvalue container as an argument to begin with. On the face of it, the problem with the code is also exemplified in



          auto it = get_data().begin();


          But std::begin is a free function template, it can be made to reject rvalues without needing to add the proper reference qualifiers to each container's begin members. By "just" forwarding it misses an opportunity to add a layer of memory safety to code.



          Ideally, the overload set could have benefited from the addition of



          template< class C > 
          void begin( C&& ) = delete;


          That one would have caused the code in the blog post to be flat out rejected on the spot.






          share|improve this answer





















          • 1





            Is it possible for us to make a warning of deprecation or usage for that particular template instantiation instead of outright deleting it? Compiler specific extensions allowed.

            – Paul Stelian
            Feb 11 at 9:51






          • 4





            @PaulStelian - Here's how btw, pure C++14. coliru.stacked-crooked.com/a/7c99059b5b1a8dca

            – StoryTeller
            Feb 11 at 10:01






          • 3





            @PaulStelian - No, we can't. I intentionally provided an example in another namespace. To add this overload, we'd need to write a proposal, then get it voted int o the standard.

            – StoryTeller
            Feb 11 at 11:25






          • 3





            The thing is, as Alexandrescu points it out with humour in its 2018 cppcon talk, the C++ committee likes to be consistent in its past errors. One might think the reason why std::begin accepts r-values is to let begin(c) and c.begin() be perfectly equivalent. (but yes obviously this overload set would be ideal)

            – YSC
            Feb 11 at 12:24








          • 3





            @YSC .begin() could also be made to reject rvalues, couldn't it? iterator begin() && = delete;

            – The Vee
            Feb 11 at 18:00
















          51












          51








          51







          I think Eric's point about std::begin is that it silently accepts an rvalue container as an argument to begin with. On the face of it, the problem with the code is also exemplified in



          auto it = get_data().begin();


          But std::begin is a free function template, it can be made to reject rvalues without needing to add the proper reference qualifiers to each container's begin members. By "just" forwarding it misses an opportunity to add a layer of memory safety to code.



          Ideally, the overload set could have benefited from the addition of



          template< class C > 
          void begin( C&& ) = delete;


          That one would have caused the code in the blog post to be flat out rejected on the spot.






          share|improve this answer















          I think Eric's point about std::begin is that it silently accepts an rvalue container as an argument to begin with. On the face of it, the problem with the code is also exemplified in



          auto it = get_data().begin();


          But std::begin is a free function template, it can be made to reject rvalues without needing to add the proper reference qualifiers to each container's begin members. By "just" forwarding it misses an opportunity to add a layer of memory safety to code.



          Ideally, the overload set could have benefited from the addition of



          template< class C > 
          void begin( C&& ) = delete;


          That one would have caused the code in the blog post to be flat out rejected on the spot.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Feb 12 at 6:42

























          answered Feb 11 at 8:47









          StoryTellerStoryTeller

          105k13221285




          105k13221285








          • 1





            Is it possible for us to make a warning of deprecation or usage for that particular template instantiation instead of outright deleting it? Compiler specific extensions allowed.

            – Paul Stelian
            Feb 11 at 9:51






          • 4





            @PaulStelian - Here's how btw, pure C++14. coliru.stacked-crooked.com/a/7c99059b5b1a8dca

            – StoryTeller
            Feb 11 at 10:01






          • 3





            @PaulStelian - No, we can't. I intentionally provided an example in another namespace. To add this overload, we'd need to write a proposal, then get it voted int o the standard.

            – StoryTeller
            Feb 11 at 11:25






          • 3





            The thing is, as Alexandrescu points it out with humour in its 2018 cppcon talk, the C++ committee likes to be consistent in its past errors. One might think the reason why std::begin accepts r-values is to let begin(c) and c.begin() be perfectly equivalent. (but yes obviously this overload set would be ideal)

            – YSC
            Feb 11 at 12:24








          • 3





            @YSC .begin() could also be made to reject rvalues, couldn't it? iterator begin() && = delete;

            – The Vee
            Feb 11 at 18:00
















          • 1





            Is it possible for us to make a warning of deprecation or usage for that particular template instantiation instead of outright deleting it? Compiler specific extensions allowed.

            – Paul Stelian
            Feb 11 at 9:51






          • 4





            @PaulStelian - Here's how btw, pure C++14. coliru.stacked-crooked.com/a/7c99059b5b1a8dca

            – StoryTeller
            Feb 11 at 10:01






          • 3





            @PaulStelian - No, we can't. I intentionally provided an example in another namespace. To add this overload, we'd need to write a proposal, then get it voted int o the standard.

            – StoryTeller
            Feb 11 at 11:25






          • 3





            The thing is, as Alexandrescu points it out with humour in its 2018 cppcon talk, the C++ committee likes to be consistent in its past errors. One might think the reason why std::begin accepts r-values is to let begin(c) and c.begin() be perfectly equivalent. (but yes obviously this overload set would be ideal)

            – YSC
            Feb 11 at 12:24








          • 3





            @YSC .begin() could also be made to reject rvalues, couldn't it? iterator begin() && = delete;

            – The Vee
            Feb 11 at 18:00










          1




          1





          Is it possible for us to make a warning of deprecation or usage for that particular template instantiation instead of outright deleting it? Compiler specific extensions allowed.

          – Paul Stelian
          Feb 11 at 9:51





          Is it possible for us to make a warning of deprecation or usage for that particular template instantiation instead of outright deleting it? Compiler specific extensions allowed.

          – Paul Stelian
          Feb 11 at 9:51




          4




          4





          @PaulStelian - Here's how btw, pure C++14. coliru.stacked-crooked.com/a/7c99059b5b1a8dca

          – StoryTeller
          Feb 11 at 10:01





          @PaulStelian - Here's how btw, pure C++14. coliru.stacked-crooked.com/a/7c99059b5b1a8dca

          – StoryTeller
          Feb 11 at 10:01




          3




          3





          @PaulStelian - No, we can't. I intentionally provided an example in another namespace. To add this overload, we'd need to write a proposal, then get it voted int o the standard.

          – StoryTeller
          Feb 11 at 11:25





          @PaulStelian - No, we can't. I intentionally provided an example in another namespace. To add this overload, we'd need to write a proposal, then get it voted int o the standard.

          – StoryTeller
          Feb 11 at 11:25




          3




          3





          The thing is, as Alexandrescu points it out with humour in its 2018 cppcon talk, the C++ committee likes to be consistent in its past errors. One might think the reason why std::begin accepts r-values is to let begin(c) and c.begin() be perfectly equivalent. (but yes obviously this overload set would be ideal)

          – YSC
          Feb 11 at 12:24







          The thing is, as Alexandrescu points it out with humour in its 2018 cppcon talk, the C++ committee likes to be consistent in its past errors. One might think the reason why std::begin accepts r-values is to let begin(c) and c.begin() be perfectly equivalent. (but yes obviously this overload set would be ideal)

          – YSC
          Feb 11 at 12:24






          3




          3





          @YSC .begin() could also be made to reject rvalues, couldn't it? iterator begin() && = delete;

          – The Vee
          Feb 11 at 18:00







          @YSC .begin() could also be made to reject rvalues, couldn't it? iterator begin() && = delete;

          – The Vee
          Feb 11 at 18:00













          13














          The temporary vector returned by get_data goes out of scope after std::begin is done. It is not kept alive, so it is an iterator into a destroyed object.






          share|improve this answer




























            13














            The temporary vector returned by get_data goes out of scope after std::begin is done. It is not kept alive, so it is an iterator into a destroyed object.






            share|improve this answer


























              13












              13








              13







              The temporary vector returned by get_data goes out of scope after std::begin is done. It is not kept alive, so it is an iterator into a destroyed object.






              share|improve this answer













              The temporary vector returned by get_data goes out of scope after std::begin is done. It is not kept alive, so it is an iterator into a destroyed object.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Feb 11 at 7:38









              Jesper JuhlJesper Juhl

              17.6k32647




              17.6k32647























                  4














                  Is it fair to say this is a memory safety failing of std::begin?
                  There is no 'safe' way of creating an iterator such that it will be valid to follow the pointer after the container is deleted.



                  It lacks a check that another method has, but it's not like there is no way to make a ranges derived iterator go pop. You just have to try a bit harder...






                  share|improve this answer




























                    4














                    Is it fair to say this is a memory safety failing of std::begin?
                    There is no 'safe' way of creating an iterator such that it will be valid to follow the pointer after the container is deleted.



                    It lacks a check that another method has, but it's not like there is no way to make a ranges derived iterator go pop. You just have to try a bit harder...






                    share|improve this answer


























                      4












                      4








                      4







                      Is it fair to say this is a memory safety failing of std::begin?
                      There is no 'safe' way of creating an iterator such that it will be valid to follow the pointer after the container is deleted.



                      It lacks a check that another method has, but it's not like there is no way to make a ranges derived iterator go pop. You just have to try a bit harder...






                      share|improve this answer













                      Is it fair to say this is a memory safety failing of std::begin?
                      There is no 'safe' way of creating an iterator such that it will be valid to follow the pointer after the container is deleted.



                      It lacks a check that another method has, but it's not like there is no way to make a ranges derived iterator go pop. You just have to try a bit harder...







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Feb 12 at 0:37









                      drjpizzledrjpizzle

                      19113




                      19113























                          2














                          Because it allows initialisation from an rvalue, which is bad.






                          share|improve this answer




























                            2














                            Because it allows initialisation from an rvalue, which is bad.






                            share|improve this answer


























                              2












                              2








                              2







                              Because it allows initialisation from an rvalue, which is bad.






                              share|improve this answer













                              Because it allows initialisation from an rvalue, which is bad.







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Feb 12 at 13:39









                              ANoneANone

                              1604




                              1604























                                  0














                                  in fact , the complicated function can be simplified to two short functions , such as



                                  int& foo(int x){
                                  return x;
                                  }
                                  int generate_a_int(){
                                  return 42;
                                  }


                                  and then invoke it foo(generate_a_int()), a temporary value is generated , once out of the function body, the temporary value generated by generate_a_int() is destroy , and then dangle reference is happened ...



                                  do you understand now?






                                  share|improve this answer




























                                    0














                                    in fact , the complicated function can be simplified to two short functions , such as



                                    int& foo(int x){
                                    return x;
                                    }
                                    int generate_a_int(){
                                    return 42;
                                    }


                                    and then invoke it foo(generate_a_int()), a temporary value is generated , once out of the function body, the temporary value generated by generate_a_int() is destroy , and then dangle reference is happened ...



                                    do you understand now?






                                    share|improve this answer


























                                      0












                                      0








                                      0







                                      in fact , the complicated function can be simplified to two short functions , such as



                                      int& foo(int x){
                                      return x;
                                      }
                                      int generate_a_int(){
                                      return 42;
                                      }


                                      and then invoke it foo(generate_a_int()), a temporary value is generated , once out of the function body, the temporary value generated by generate_a_int() is destroy , and then dangle reference is happened ...



                                      do you understand now?






                                      share|improve this answer













                                      in fact , the complicated function can be simplified to two short functions , such as



                                      int& foo(int x){
                                      return x;
                                      }
                                      int generate_a_int(){
                                      return 42;
                                      }


                                      and then invoke it foo(generate_a_int()), a temporary value is generated , once out of the function body, the temporary value generated by generate_a_int() is destroy , and then dangle reference is happened ...



                                      do you understand now?







                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Feb 14 at 9:37









                                      lisuwanglisuwang

                                      223




                                      223






























                                          draft saved

                                          draft discarded




















































                                          Thanks for contributing an answer to Stack Overflow!


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.




                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54625792%2fwhy-are-stdbegin-and-stdend-not-memory-safe%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          Popular posts from this blog

                                          Questions related to Moebius Transform of Characteristic Function of the Primes

                                          List of scandals in India

                                          Can not write log (Is /dev/pts mounted?) - openpty in Ubuntu-on-Windows?