Does Ranged for loop of variables return the address link of a local variable?

// g++ --std=c++17 test.cpp -I /usr/local/include -L /usr/local/lib -lboost_system -Wall -pedantic -Wreturn-type -Wstrict-aliasing -Wreturn-local-addr -fsanitize=address -g
// LD_LIBRARY_PATH=/usr/local/lib ./a.out

#include <iostream>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

class A {
public:
    fs::path path_;

    const fs::path & path() const { return path_; }
    fs::path & path() { return path_; }
};

class B {
public:
    fs::path root_path_;

    A path_2;
    A path_3;

    const fs::path & operator()() const {
        for ( const auto & path : {
            path_3.path(),
            path_2.path(),
            root_path_
        }) {
            if ( not path.empty() ) {
                return path;
            }
        }
        throw std::logic_error{"using default-constructed B"};
    }
};

int main(int argc, char **argv) {
    B b;
    b.root_path_ = "foo/";
    b.path_2.path() = "foo/bar";
    b.path_3.path() = "foo/baz";

    std::cout << b() << '\n';

    return 0;
}

With the above code, which as far as I know seems to be valid C ++. Instead, when I call, I get garbage output.

g++Don't complain initially, however the Sanitizer address does. g++finally complains when adding -O2. Created Alert

test.cpp: In member function ‘const boost::filesystem::path& B::operator()() const’:
test.cpp:31:12: warning: function may return address of local variable [-Wreturn-local-addr]
     return path;
            ^~~~
test.cpp:29:3: note: declared here
   }) {
   ^

Please note that I use:

$ cat /etc/fedora-release 
Fedora release 25 (Twenty Five)
$ g++ --version
g++ (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Note that I resolved the error by specifying a pointer instead.

    const fs::path & operator()() const {
            for ( const auto * path : {
                    &path_3.path(),
                    &path_2.path(),
                    &root_path_
            }) {
                    if ( not path->empty() ) {
                            return *path;
                    }
            }
            throw std::logic_error{"using default-constructed B"};
    }

But that leaves me with a few questions:

  • Why g++doesn't he complain about the problem until it is added -O2?
  • undefined? , : B::operator() const - ... ... const. , , , , . -. const auto &, ... const member. , ?
+4
1
  • undefined. , undefined, , . gcc -O2 ; gcc undefined , .

  • , std::initializer_list. ​​ . , , , gcc. , , . undefined.

, , , .

:

. std:: initializer_list (.. , , ).

, , , . . , , .

+5

Source: https://habr.com/ru/post/1671556/


All Articles