Is this a compiler bug? Am I doing something wrong

2019-02-25 09:23发布

I'm trying to make a simple map to look up some data, but the results are coming out very strange:

#include "stdafx.h"
#include "atlstr.h"
#include <map>

enum InputTypes { Manual, Automatic, Assisted, Imported, Offline };

struct Params
{
    int inputType;
    const char* moduleName;
    DWORD flag;
};

int _tmain()
{
    std::map<CString, Params> options {
        { "Add",       { Manual,    "RecordLib",  0 } },
        { "Open",      { Assisted,  "ViewLib",    1 } },
        { "Close",     { Imported,  "EditLib",    2 } },
        { "Inventory", { Automatic, "ControlLib", 3 } },
        { "Report",    { Offline,   "ReportLib",  4 } }
    };

    for (std::map<CString, Params>::iterator iter = options.begin(); iter != options.end(); ++iter)
    {
        printf("Entry: %s ==> { %d, %s, %d }\n", (const char*)(iter->first),
            iter->second.inputType, iter->second.moduleName, iter->second.flag);
    }


    return 0;
}

Output:

Entry: îþîþîþîþîþîþîþîþîþîþîþîþ[â0; t ==> { 0, RecordLib, 0 }
Entry: Close ==> { 3, EditLib, 2 }
Entry: Inventory ==> { 1, ControlLib, 3 }
Entry: îþîþîþîþîþîþîþîþîþîþîþîþCâ0# t ==> { 2, ViewLib, 1 }
Entry: Report ==> { 4, ReportLib, 4 }

As you can see, a couple of the CString values turned to garbage. But I don't see any reason why I couldn't create a map this way.

Is this a bug in the Microsoft Visual Studio 2013 compiler?
Is there something peculiar about my code that I'm missing?

############ Edit ##############

For those who think this is a problem with CString, I re-wrote it with std::string, and got worse output:

#include "stdafx.h"
#include "atlstr.h"
#include <map>

enum InputTypes { Manual, Automatic, Assisted, Imported, Offline };

struct Params
{
    int inputType;
    std::string moduleName;
    DWORD flag;
};

int _tmain(int argc, _TCHAR* argv[])
{
    std::map<std::string, Params> options{
        { "Add",       { Manual, "RecordLib", 0 } },
        { "Open",      { Assisted, "ViewLib", 1 } },
        { "Close",     { Imported, "EditLib", 2 } },
        { "Inventory", { Automatic, "ControlLib", 3 } },
        { "Report",    { Offline, "ReportLib", 4 } }
    };

    for (std::map<std::string, Params>::iterator iter = options.begin(); iter != options.end(); ++iter)
    {
        printf("Entry: %s ==> { %d, %s, %d }\n", iter->first.c_str(),
            iter->second.inputType, iter->second.moduleName.c_str(), iter->second.flag);
    }
    return 0;
}

Output

Entry:  ==> { 0, , 0 }
Entry: Report ==> { 4, , 4 }

Note that this does work on IDEOne

1条回答
爷、活的狠高调
2楼-- · 2019-02-25 09:51

I have copied you example into MSVC. It is even more than incorret printing - it is a memory violation in ATL CString upon destruction of map. But all works with std::string. Conclusion - buggy ATL implementation. If I am to take a wild guess, I'd say, it's a bug in move constructor.

查看更多
登录 后发表回答