I have following program:
#include <cstdio>
import animal;
int main() {
auto s = makeSound();
printf("%s", s.c_str());
return 0;
}
and module interface:
module;
#include <string>
export module animal;
import :sound;
export std::string makeSound() {
return makeSound_Impl();
}
and module implementation unit:
module;
#include <string>
module animal:sound;
std::string makeSound_Impl() {
return "Wroooarrh";
}
Program is compiled with:
g++ -fmodules-ts -g -std=c++20 animal_sound.cpp -c -o animal_sound.o
g++ -fmodules-ts -g -std=c++20 animal.cpp -c -o animal.o
g++ -fmodules-ts -g -std=c++20 animal.o animal_sound.o main.cpp -o main.exe
Compiler version:
g++ --version
g++ (Ubuntu 13.1.0-8ubuntu1~22.04) 13.1
Program crashes on basic_string:
Program received signal SIGSEGV, Segmentation fault.
0x00005555555566c2 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_data (this=0xd00aa32b9e55bf00) at /usr/include/c++/13/bits/basic_string.h:223
223 { return _M_dataplus._M_p; }
(gdb) bt
#0 0x00005555555566c2 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_data (this=0x0) at /usr/include/c++/13/bits/basic_string.h:223
#1 0x0000555555556f3a in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str (this=0x7fffffffda50) at /usr/include/c++/13/bits/basic_string.h:2584
#2 0x0000555555556ea6 in main () at main.cpp:7
When compiled with module ‘animal’ defining makeSound
directly (not working as proxy to implementation unit):
module;
#include <string>
export module animal;
export std::string makeSound() {
return "Sound!";
}
Everything works fine (program does not crash). Am I doing something wrong, or that’s a compiler issue?
EDIT
Interestingly I was able to reproduce the issue without implementation units. If no include <string>
is present in module ‘animal’ then problem is gone.
module;
#include <string>
export module animal:sound;
export std::string makeSound() {
return "Wroooarrh";
}
module;
// #include <string> // Adding include makes program crash
export module animal;
export import :sound;
EDI2
Reported bug on GCC Bugzilla: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111447
2
Answers
Two ways to make this work
I found two ways to make this work.
animal:sound
from an implementation unit into an interface unit.animal:sound
, and add an implementation unit for moduleanimal
.These solutions were tests using MSVC.
Method 1
This was the simpler of the two methods.
I merely added the keyword
export
to the module declaration for moduleanimal:sound
.Nothing else was changed, and the program ran fine.
I am still unsure what to make of Microsoft’s explanation that, "A partition has an interface file, and zero or more implementation files." (See Module partition files.)
If true, that would explain the problems cited in the OP. The program there has an implementation unit for the partition
animal:sound
, but no accompanying interface unit.In a cursory reading of the material at CppReference, and an even quicker scan of "Section 10.1 Module units and purviews" in the C++ Standard, I could not confirm the Microsoft statement.
Method 2
Another way to make this work is to create a module implementation unit for module
animal
directly.This method eliminates the module partition
animal:sounds
.The main routine is identical to that in the original question.
Next comes the module interface unit for module
animal
.One of the advantages to using
.ixx
for interface units is that.cpp
is available for implementation units. Hence the nameanimal.cpp
below.The output is as expected:
The problem you seem to be having is due to each of the module units in the same module having a
#include <string>
in them. This should not be a problem; there should be nothing wrong with different module units in the same module including the same header in their global module fragments. But your compiler won’t seem to let you do it.That makes it a compiler bug.