lundi 29 août 2016

C++11 lambda operator namespace conflict

I have three files, main.cpp, a.cpp and b.cpp. The main() function just calls a function in a.cpp, and then in b.cpp -- and I get a SIGSEGV. As far as I can tell, it looks like the lambda functions used with my sort() are conflicting with each other. Compile command line order is important; if I compile the files via:

g++ -std=c++11 main.cpp a.cpp b.cpp

The code crashes (I get "*** stack smashing detected ***: ./a.out terminated"), but if I switch "a.cpp" and "b.cpp":

g++ -std=c++11 main.cpp b.cpp a.cpp

it runs fine (I'm not saying anything about whether it "works" or not, just SIGSEGV vs no-SIGSEGV).

Here's the smallest code samples I could generate for the three files:

main.cpp:

extern void spud1 (void);
extern void spud2 (void);

int
main (int argc, char **argv)
{
    spud1 ();
    spud2 ();
}

a.cpp:

#include <vector>
#include <string>
#include <algorithm>

using namespace std;

struct Database
{
    int     pubdate;
    string  title;
    string  link;
};

static vector <Database> database;

void
spud1 (void)
{
    int     i;

    for (i = 0; i < 20; i++) {
        database.push_back ({});
    }

    sort(database.begin(), database.end(),
        [] (const Database& a, const Database& b)
        {
            return (a.pubdate > b.pubdate);
        });
}

b.cpp:

#include <vector>
#include <string>
#include <algorithm>

using namespace std;

struct Database
{
    unsigned        serial;
    double          calories;
    double          carbs;
    double          sodium;
    double          sugar;
};

static vector <Database> database;

void
spud2 (void)
{
    int     i;

    for (i = 0; i < 20; i++) {
        database.push_back ({});
    }

    sort(database.begin(), database.end(),
        [] (const Database& a, const Database& b)
        {
            return (a.serial > b.serial);
        });
}

There are two things that bother me about this:

  1. there's no indication from the toolchain that "something bad" is happening; there are no compiler or linker warnings, and
  2. I have no way to make "struct Database" local to the module -- if I stick "static" in front of it I get an error: "a.cpp:13:1: error: a storage class can only be specified for objects and functions**`"

So, my question is, what am I doing wrong, and how can I get around it? (i.e., why is there no warning, is this "supposed" to happen? and how do I make my "Database" struct actually be local to the module? -- my workaround is to use different names, but I'm not happy with that.)

Aucun commentaire:

Enregistrer un commentaire