【问题标题】:c++ modules and "multiple definition of"c++模块和“多重定义”
【发布时间】:2021-11-28 18:54:54
【问题描述】:

我正在尝试学习一些关于 c++ 模块的知识。我编写了简单的源代码,我试图在没有运气的情况下进行编译。出于某种原因,我遇到了多个定义的链接器问题,但我不明白原因。我的 g++ 版本是来自 cygwin 的 11.2。我的代码中有错误吗?是别的吗?

$ g++ -std=c++20 -fmodules-ts module_a.cpp module_b.cpp main.cpp
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0xc): multiple definition of `std::string::_Alloc_hider::~_Alloc_hider()'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0xc): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0xc): multiple definition of `std::string::_Alloc_hider::~_Alloc_hider()'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0xc): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0x28): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0x28): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0x28): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0x28): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0x82): multiple definition of `std::string::_Alloc_hider::_Alloc_hider(char*, std::allocator<char> const&)'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0x82): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0x82): multiple definition of `std::string::_Alloc_hider::_Alloc_hider(char*, std::allocator<char> const&)'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0x82): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0xb8): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&)'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0xb8): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/11/../../../../x86_64-pc-cygwin/bin/ld: /tmp/ccfWIJyE.o:module_b.cpp:(.text+0xb8): multiple definition of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&)'; /tmp/cc8Ygf2b.o:module_a.cpp:(.text+0xb8): first defined here
collect2: error: ld returned 1 exit status

ma​​in.cpp:

import module_a;
import module_b;

int main()
{
    test_a();
    test_b();
}

module_a.cpp:

module;

import <iostream>;

export module module_a;

export void test_a()
{
    std::cout << std::string("test module a\n");
}

module_b.cpp:

module;

import <iostream>;

export module module_b;

export void test_b()
{
    // std::cout << "test module b\n";           // <- this works
    std::cout << std::string("test module b\n"); // <- this cause the issue
}

【问题讨论】:

  • 您是否尝试先单独构建标准标头?像这样:g++ -std=c++20 -fmodules-ts -xc++-system-header iostream。您是否也尝试在两个文件中对stringimport &lt;string&gt;; 执行相同的操作?您可能还希望将导入声明移出全局模块片段并移入模块中,以便同时导出 std::coutstd::string() 的功能。

标签: c++ gcc c++-modules


【解决方案1】:

我不确定您的示例中出了什么问题,可能有几件事(请查看我对问题的评论)。无论如何,这段代码应该可以正常工作:

// module_a.cpp
export module module_a;

import <iostream>;
import <string>;

export void test_a()
{
    std::cout << std::string("test module a\n");
}
// module_b.cpp
export module module_b;

import <iostream>;
import <string>;

export void test_b()
{
    std::cout << std::string("test module b\n");
}
// main.cpp
import module_a;
import module_b;

int main()
{
    test_a();
    test_b();

    return 0;
}
# Makefile
GCC=g++-11 -std=c++20 -fmodules-ts

all: std_headers module_a.o module_b.o main

std_headers:
    $(GCC) -xc++-system-header iostream
    $(GCC) -xc++-system-header string

module_a.o: module_a.cpp
    $(GCC) -c $< -o $@

module_b.o: module_b.cpp
    $(GCC) -c $< -o $@

main: main.cpp module_a.o module_b.o
    $(GCC) $^ -o $@

clean:
    rm -f *.o
    rm -rf gcm.cache/
    rm -f main

如果我猜测一下,可能是您在全局模块片段中而不是在模块声明中导入iostream,在这种情况下,iostream 的定义,例如“std::cout”也不会导出。

$ make
g++-11 -std=c++20 -fmodules-ts -xc++-system-header iostream
g++-11 -std=c++20 -fmodules-ts -xc++-system-header string
g++-11 -std=c++20 -fmodules-ts -c module_a.cpp -o module_a.o
g++-11 -std=c++20 -fmodules-ts -c module_b.cpp -o module_b.o
g++-11 -std=c++20 -fmodules-ts main.cpp module_a.o module_b.o -o main

$ ./main
test module a
test module b

$ g++-11 --version | head -n 1
g++-11 (Ubuntu 11.1.0-1ubuntu1~20.04) 11.1.0

【讨论】:

  • 感谢您的调查。我刚刚使用您的代码和 Makefile 进行了检查。不幸的是,我仍然遇到这个问题。我怀疑它与cygwin环境有关。看起来我必须更改编译器,因为来自 cygwin 的编译器并不是很稳定。例如,我可以在 MSVC++ 上毫无问题地编译我的代码。
  • @Adam 我认为我们将不得不等待几年的编译器稳定性。 Linux 上的 GCC 也有几个缺点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-29
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多