Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ modules: Multiply defined symbols no longer an error?

If you have two classic translation units which both define the same symbol (let’s say auto fun0() -> void), I get a fatal error LNK1169: one or more multiply defined symbols found in MSVC as it violates the ODR.

One of the first steps I made with C++ modules was trying out the behavior with that basic principle. So we have two module files (module0.ixx and module1.ixx) with this almost identical content:

// module0.ixx
export module module0;
import <cstdio>;
export void f_test() { printf("f_test()\n"); }

// module1.ixx
export module module1;
import <cstdio>;
export void f_test() { printf("f_test()\n"); }

In my main.cpp, I do

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import module0;
import module1;
auto main() -> int{
    f_test();
}

To my surprise, this compiles just fine. With that come the expected problems: If the definition is different, the behavior depends on the order etc. Is this expected? This was 5 minutes into playing around with modules and seems pretty baffling.

>Solution :

"Multiply defined symbols no longer an error?" – They were never required to be an error. Violation of the ODR is "ill-formed; no diagnostic required". Which basically means undefined behavior ensues, like you see here.

This issue is not specifically endemic to modules. "Old C++" can exhibit the same behavior.

// oops_header.h
#ifndef OOPS
#error OOPS
#endif

#include <iostream>

inline void oops_func() { std::cout << OOPS; }

And we the same shenanigans when we include it and mess with the macro

// tu1.cpp
#define OOPS 123
#include <oops_header.h>
void a() { oops_func(); }

// tu2.cpp
#define OOPS 42
#include <oops_header.h>
void b() { oops_func(); }

Where a main function like this

extern void a();
extern void b();
int main() {
  a();
  b();
}

Will exhibit the exact same problems you encountered with the modules. The output will depend on the stars, because I violated the ODR (inline functions are required by the ODR to be identical on the token level).

You see it with modules due to an artefact of their implementation today (kinda similar to precompiled headers).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading