1

Good day,
I'm trying new things in C++ and I found case where Debug and Release configurations in Visual Studio gave me a different results.

#include <experimental/generator>
#include <fstream>
#include <functional>
#include <iostream>
#include <string>
#include <vector>


template <typename T = std::string>
auto getLineByLine(std::string filename, std::function<T(std::string&)> func = [](std::string& var) { return var; })
{
    std::ifstream infile(filename);
    std::string line;

    while (getline(infile, line))
    {
        yield func(line);
    }
}

int main()
{
    std::vector<std::string> myVector;
    for (const auto& line : getLineByLine("fileWithMoreThanOneLine.txt"))
    {
        myVector.push_back(line);
    }
    std::cout << myVector[0] << std::endl;
}

This code in Debug outputs as expected - one line from file fileWithMoreThanOneLine.txt.
But in Release it crashes on last line when I'm printing first string in vector.
When I tried to debug it I found that variable myVector was "optimized away and not available." in Release. I think this is not right optimization.

Also I found that if I change one line to this:
for (const auto& line : getLineByLine("fileWithMoreThanOneLine.txt", [&myVector](std::string& var) { return var; }))
it compiles correctly. But variable myVector is not needed in lambda function, right?

Is this problem with my code or MSVC compiler? I tried VS 2015 Update 1 (first VS with coroutines) and VS "15" with daily build of VC++.

Thank you,
Miroslav Hrnčíř

P.S. I'm sorry for my bad English and if it's dumb question.

CdTCzech
  • 23
  • 5
  • What is `program`? – SomeWittyUsername Oct 05 '16 at 10:07
  • and also in your current code you never push anything into `myVector` – Hayt Oct 05 '16 at 10:07
  • Oh sorry, program is original name for myVector :( – CdTCzech Oct 05 '16 at 10:08
  • Sounds like it could be an issue in MSVC. Just curious, what if you change your loop to `for (auto line : getLineByLine("fileWithMoreThanOneLine.txt"))`? I think that `getLineByLine` returns a temporary, and although a const ref should not cause an issue per the standard, maybe it is? – AndyG Oct 05 '16 at 10:25
  • @AndyG Great idea, but this is not the problem. – CdTCzech Oct 05 '16 at 10:44
  • Can you print the vector's size before you print the first element? – AndyG Oct 05 '16 at 10:57
  • @AndyG 49 in Debug (correct), random number in Release. But when it goes from loop (in Release) myVector size is 49. – CdTCzech Oct 05 '16 at 11:06
  • @CdTCzech: Definitely a MSVC problem. Do you have compiler flag /ZI set? Apparently this can cause bad code generation. Otherwise, it's just another bug that will eventually get fixed. In the meantime you could implement your own co-routines with C++11 features. – AndyG Oct 05 '16 at 11:33

1 Answers1

1

Sounds like it's an issue with your file path ... you're probably not able to read the file, resulting in the vector not being populated, and then the vector[0] is out of range.

VS places the release build and the debug build in different directories, meaning that the file you're opening when you run with a debug build doesn't exist with the same relative path you've used.

Try updating it with a full path and then see what happens

UKMonkey
  • 6,941
  • 3
  • 21
  • 30
  • That is exactly the point - they have different run directories, and it's just a file name. Can't assume that they're run from the same spot. Plus it's more likely that OP has done something wrong like this, than MSVC has released a library that can't open files with a release build. – UKMonkey Oct 05 '16 at 10:29
  • Haha that's totally true. Perhaps the txt file is only in Debug. Good point. – AndyG Oct 05 '16 at 10:30
  • Thanks for the response, but it reads everything in Debug correctly from the file and Release mode just turns on optimization flags. – CdTCzech Oct 05 '16 at 10:31
  • @CdTCzech: And what happens if you use an absolute file path? – AndyG Oct 05 '16 at 10:31
  • Updated the answer to explain why the path could be the issue – UKMonkey Oct 05 '16 at 10:37
  • @UKMonkey This is not the problem. I tried it with absolute file path and it is the same problem. btw I can see in debugger that file is opened and all 48 lines are read correctly. – CdTCzech Oct 05 '16 at 10:42
  • So you can add std::cout << line << std::endl; in the loop and it works correctly? – UKMonkey Oct 05 '16 at 10:47
  • @UKMonkey Yeah, no matter if path is absolute or relative. But interesting thing is that myVector lives in the loop, but after the loop myVector is destroyed... – CdTCzech Oct 05 '16 at 10:53
  • Ok - attempt 2 time :D What if you make the vector volatile - looks like resumable functions may be run on other threads, meaning that the compiler would consider that your vector would never be changed – UKMonkey Oct 05 '16 at 10:53
  • @UKMonkey If I'm right myVector can't be volatile because push_back() is not volatile function. http://stackoverflow.com/questions/4812256/problems-with-stl-as-a-static-volatile-member – CdTCzech Oct 05 '16 at 11:01