jeudi 20 juin 2019

Range based for loop not executing

I'm experiencing a weird behavior in a range based for loop over a map in C++ under Ubuntu 18.04 (with or without VisualStudio) and I've tried many rewrites unsuccessfully. Everything I found here and in the rest of the WWW just showed conceptual basics of the range based loop or trivial mistakes.

This is a VisualStudio C++ Linux project, whose language standard is set to C11, C++11 (-std=c11, -std=c++11). There are also GNU variants (-std=gnu11 and -std=gnu++11) and I even tried C++17, however they didn't make any difference.

Basically, I have the following classes: a transmission handler called MyTransmitter, a data cache called MyCache and a data object called MyData. The following code shows the definition of a method that iterates over the data objects in order to transmit and mark them as sent:

void MyTransmitter::Transmit()
{
    map<const string, MyData> alldata = this->Cache.CurrentData;

    for (pair<const string, MyData> kvp : alldata)
    {
        Data data = kvp.second;
        // do stuff
        kvp.second.IsTransferred = true;
    }
}

Problem: After rewriting my initial naive attempt to a range based loop the program stopped transmitting anything and so I started debugging in VisualStudio 2017 (I didn't see any error, btw.). I was able to reproduce that the first line is executed, but when I try to run the next command (which is the for loop), the execution focus jumps immediately to the end of the method. With a breakpoint at the start of the method I saw that the alldata variable has been assigned something, but I only see alldata {...} when I hover over it. The Cache part allowed me to see a bit more, when I hovered over it and I could navigate via CurrentData to nothing more but a message like subordinate elements could not be evaluated (or something along those lines, German version).

For clarity I add the shortened class headers here:

MyTransmitter.h:

#include <iostream>
#include "MyCache.h"
#include <cstdlib>
#include <iomanip>
#include <map>

using namespace std;

class MyTransmitter
{
public:
    MyTransmitter(MyCache cache, const string x, const string y);
    ~MyTransmitter();

    void Transmit();

private:
    MyCache Cache;
    string X;
    string Y;
}

MyCache.h:

#include <regex>
#include <string>
#include "MyData.h"
#include <map>

using namespace std;

class MyCache
{
public:
    MyCache();
    ~MyCache();

    void Register(string key, bool z);
    void Deregister(string key);
    void Change(string key, double value);

    map<const string, MyData> CurrentData;
}

MyData.h:

#include <string>
#include <chrono>
#include <cmath>

using namespace std;

typedef chrono::high_resolution_clock MyClock;
typedef chrono::nanoseconds MyTimeSpan;
typedef chrono::time_point<chrono::system_clock, MyTimeSpan> MyTimePoint;

class MyData
{
public:
    MyData();
    ~MyData();

    bool IsTransferred;
    bool Z;
    string Key;
    double PreviousValue;
    double CurrentValue;
    MyTimePoint PrevousTimeStamp;
    MyTimePoint CurrentTimeStamp;
}

To invoke the problematic piece, the main() method looks like:

#include <cstdio>
#include <cstdlib>
#include <regex>
#include <string>
#include <iostream>
#include <unistd.h>
#include <time.h>
#include <chrono>
#include <hash_map> // I also tried <map>
#include "MyTransmitter.h"

int main()
{
    MyCache mc;
    MyTransmitter mt(mc, "bla", "blabla");

    InitMyData(); // this populates the cache via mc.Register() and definitely works

    // do some stuff here executing something like mc.Change("somekey", 1234.5) - also definitely working

    mt.Transmit(); // here, the problematic method is called and returns immediately

    return 0;
}

At the end of InitMyData() the cache is definitely populated correctly and the changes afterwards are OK, too, but it seems strange to me that I can't see anything later in the Transmit() method while debugging.

Question: What am I doing wrong here and how can I fix it? Is memory management playing tricks with me or am I missing some pointer stuff here or are there any silently failing ambiguities regarding the map type that I am not aware of? Is this a sign of a wrong C++ language standard?

Aucun commentaire:

Enregistrer un commentaire