C++ 模块中的向量导致无用的错误文件数据 GCC 输出
Vector in C++ module causes useless Bad file data GCC output
TL;DR: GCC 11.2.0 (image f7ea55625e09
) + C++20 + <vector>
's std::vector<anything>
导致无用的输出。如何获得我可以使用的东西?
编译适用于:
- 模块缓存
- 单个文件
- 单独的模块文件
In module imported at main.cpp:4:1: import mymodule;
mymodule: error: failed to read compiled module: Bad file data eh???????
mymodule: note: compiled module file is 'gcm.cache/mymodule.gcm' exists, 124 912 Bytes
mymodule: fatal error: returning to the gate for a mechanical issue ????????
compilation terminated.
对于 fatal
(门),我只找到了这些参考资料(1, 2),从中我的情况看起来一切正常。
我已经使用新的 C++ 模块(C++20、GCC 11.2)尝试了各种简单的事情,这让我想知道我是否只是遇到编译器错误/缺少实现或没有得到非常简单的东西。
这是一个带有 vector<string>
的简单 C++ 代码,它使用基本标志编译得很好,并输出预期的内容:
# create module cache for system headers
for item in iostream string vector
do
g++ -fmodules-ts -std=c++20 -x c++-system-header $item
done
g++ -Wall -Wextra -Wpedantic -std=c++20 -fmodules-ts main.cpp
// main.cpp
import <iostream>;
import <string>;
import <vector>;
int main() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
for (auto& item : vec) {
std::cout << item << std::endl;
}
}
$ ./a.out
Hello
world
在这里,我将矢量创建移动到一个新函数中,编译正常,工作正常。除了系统 headers.
之外仍然没有单独的模块
// main.cpp
import <iostream>;
import <string>;
import <vector>;
std::vector<std::string> create() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
return vec;
}
int main() {
std::vector<std::string> vec = create();
for (auto& item : vec) {
std::cout << item << std::endl;
}
}
在这里我将函数移动到单独的模块文件中的单独的导出函数。
g++ -Wall -Wextra -Wpedantic -std=c++20 -fmodules-ts -c mymodule.cpp
// mymodule.cpp
export module mymodule;
import <string>;
import <vector>;
export std::vector<std::string> create() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
return vec;
}
编译得很好,但是当添加到 main.cpp
、
import <iostream>;
import <string>;
import <vector>;
import mymodule;
int main() {
std::vector<std::string> vec = create();
for (auto& item : vec) {
std::cout << item << std::endl;
}
}
我只得到这个:
g++ -Wall -Wextra -Wpedantic -std=c++20 -fmodules-ts mymodule.cpp main.cpp
In module imported at main.cpp:4:1: import mymodule;
mymodule: error: failed to read compiled module: Bad file data eh???????
mymodule: note: compiled module file is 'gcm.cache/mymodule.gcm' exists, 124 912 Bytes
mymodule: fatal error: returning to the gate for a mechanical issue ????????
compilation terminated.
# file gcm.cache/mymodule.gcm
ELF 32-bit LSB no file type, no machine, version 1 (SYSV)
# file gcm.cache/usr/local/include/c++/11.2.0/iostream.gcm
ELF 32-bit LSB no file type, no machine, version 1 (SYSV)
# file a.out
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped
这似乎不是简单容器的问题,也不是单独 <vector>
的 import
声明的问题:
// mymodule.cpp
export module mymodule;
import <string>;
import <vector>;
export std::string create() {
return "world";
}
// main.cpp
import <iostream>;
import <string>;
import <vector>;
import mymodule;
int main() {
std::string vec = create();
std::cout << vec << std::endl;
}
我试过(但没有实际效果):
.cpp
vs .mpp
扩展名,尽管这无关紧要
- 每次编译前清除缓存(ref)
global module fragment (7)
展示位置即 module; [stuff]; export module mymodule;
- 单独编译 (
-c mymodule.cpp
+ -c main.cpp
) 到 link 手动(在 main.cpp
上以同样的方式失败)
- (重新)从函数
export
移动
- 不调用函数,只是导入(
import mymodule;
触发编译)
- 从
std::vector<std::string>
切换到 std::vector<int>
以查看模板的参数列表是否导致问题
- 从
std::vector<std::string>
切换到std::pair<int, int>
然后切换到std::pair<std::string, std::string>
(使用<utility>
header模块缓存)看看是否只是<vector>
对我来说坏了
看起来问题是由 <vector>
header 引起的。任何想法我怎样才能撬开 GCC 给我一些比“naaah,做不到”更好的东西?至少我可以使用 -S
(3k+ 行)生成程序集或使用 hexdump
/ objdump
来生成 gcm.cache/mymodule.gcm
并查看二进制文件,但我不确定要做什么寻找因为无用的输出。
编辑: 看起来像是架构问题?
- 使用
-m64
对模块缓存没有任何作用,仍然是 32 位
- 使用
-m32
(apk install -y g++-multilib
on 64bit)returns 相同的输出
编辑 2: 所以我在 this article 的帮助下重写了一点以使其与 Clang 12 (b978a93
) 兼容,但事实并非如此1:1 有点像屠杀(string_view
注意),但也许我没有看到更广泛的图景或缺少某些东西。
我认为我不应该包括 <string_view>
,因为那应该是自动包括的。否则,即使我编写了我的模块,我也可以从实现中每隔 #include
开始 copy-pasting,直到剩下 none,这样我就可以确保文件顺序(然后又是什么模块的点)。
// mymodule.cpp
module;
// no proper "import" available yet, so switching to the old includes
#include <string>
#include <vector>
#include <iostream>
export module mymodule;
export std::vector<std::string> create() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
return vec;
}
// need to wrap printing for a string_view for some reason
export void printme(std::string &item) {
std::cout << item << std::endl;
}
// main.cpp
// includes needed for "auto" and usage of those types
// and were needed also for print(create()) call
// so something seems broken over here
#include <vector>
#include <string>
import mymodule;
int main() {
auto vec = create();
for (std::string item : vec) {
// string_view:142:2: note: declaration of
// 'basic_string_view<_CharT, _Traits>' does not match
// std::cout << item << std::endl;
printme(item);
}
}
clang++ -std=c++20 -c mymodule.cpp -Xclang -emit-module-interface -fimplicit-modules -fimplicit-module-maps -o mymodule.pcm
clang++ -std=c++20 -fprebuilt-module-path=. -fimplicit-modules -fimplicit-module-maps mymodule.cpp main.cpp
所以这个问题似乎是 GCC 特有的,并且很可能是一个由架构切换判断的错误(hardcoding/wrong GCC 中的代码分支?)。也许值得在 >11.2.0
.
之后重访
我正在使用 C++20 模块 (gcc 11.2.0) 编写共享库,并且对于 std::vector
自定义类型有相同的“错误文件数据”错误。就我而言,正如 已经提到的,大多数容器都会出现此错误:地图、列表等
根据您的参考,我找到了 this issue,现在有了一个临时解决方案,只需要在模块中添加这一行。
namespace std _GLIBCXX_VISIBILITY(default){}
这在我的库中与其他容器一起工作。我一直在使用编译器选项寻找合适的解决方案,但没有成功。
文件/命令
// mymodule.cpp
export module mymodule;
import <string>;
import <vector>;
namespace std _GLIBCXX_VISIBILITY(default){}
export std::vector<std::string> create() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
return vec;
}
// main.cpp
import <iostream>;
import <string>;
import <vector>;
import mymodule;
int main() {
std::vector<std::string> vec = create();
for (auto& item : vec) {
std::cout << item << std::endl;
}
}
g++ -fmodules-ts -std=c++20 -x c++-system-header iostream
g++ -fmodules-ts -std=c++20 -x c++-system-header string
g++ -fmodules-ts -std=c++20 -x c++-system-header vector
g++ -fmodules-ts -std=c++20 mymodule.cpp main.cpp
$ ./a.out
Hello
world
P.S。我不能评论,所以张贴为答案,希望它能提出来。
TL;DR: GCC 11.2.0 (image f7ea55625e09
) + C++20 + <vector>
's std::vector<anything>
导致无用的输出。如何获得我可以使用的东西?
编译适用于:
- 模块缓存
- 单个文件
- 单独的模块文件
In module imported at main.cpp:4:1: import mymodule; mymodule: error: failed to read compiled module: Bad file data eh??????? mymodule: note: compiled module file is 'gcm.cache/mymodule.gcm' exists, 124 912 Bytes mymodule: fatal error: returning to the gate for a mechanical issue ???????? compilation terminated.
对于 fatal
(门),我只找到了这些参考资料(1, 2),从中我的情况看起来一切正常。
我已经使用新的 C++ 模块(C++20、GCC 11.2)尝试了各种简单的事情,这让我想知道我是否只是遇到编译器错误/缺少实现或没有得到非常简单的东西。
这是一个带有 vector<string>
的简单 C++ 代码,它使用基本标志编译得很好,并输出预期的内容:
# create module cache for system headers
for item in iostream string vector
do
g++ -fmodules-ts -std=c++20 -x c++-system-header $item
done
g++ -Wall -Wextra -Wpedantic -std=c++20 -fmodules-ts main.cpp
// main.cpp
import <iostream>;
import <string>;
import <vector>;
int main() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
for (auto& item : vec) {
std::cout << item << std::endl;
}
}
$ ./a.out
Hello
world
在这里,我将矢量创建移动到一个新函数中,编译正常,工作正常。除了系统 headers.
之外仍然没有单独的模块// main.cpp
import <iostream>;
import <string>;
import <vector>;
std::vector<std::string> create() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
return vec;
}
int main() {
std::vector<std::string> vec = create();
for (auto& item : vec) {
std::cout << item << std::endl;
}
}
在这里我将函数移动到单独的模块文件中的单独的导出函数。
g++ -Wall -Wextra -Wpedantic -std=c++20 -fmodules-ts -c mymodule.cpp
// mymodule.cpp
export module mymodule;
import <string>;
import <vector>;
export std::vector<std::string> create() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
return vec;
}
编译得很好,但是当添加到 main.cpp
、
import <iostream>;
import <string>;
import <vector>;
import mymodule;
int main() {
std::vector<std::string> vec = create();
for (auto& item : vec) {
std::cout << item << std::endl;
}
}
我只得到这个:
g++ -Wall -Wextra -Wpedantic -std=c++20 -fmodules-ts mymodule.cpp main.cpp
In module imported at main.cpp:4:1: import mymodule; mymodule: error: failed to read compiled module: Bad file data eh??????? mymodule: note: compiled module file is 'gcm.cache/mymodule.gcm' exists, 124 912 Bytes mymodule: fatal error: returning to the gate for a mechanical issue ???????? compilation terminated.
# file gcm.cache/mymodule.gcm
ELF 32-bit LSB no file type, no machine, version 1 (SYSV)
# file gcm.cache/usr/local/include/c++/11.2.0/iostream.gcm
ELF 32-bit LSB no file type, no machine, version 1 (SYSV)
# file a.out
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped
这似乎不是简单容器的问题,也不是单独 <vector>
的 import
声明的问题:
// mymodule.cpp
export module mymodule;
import <string>;
import <vector>;
export std::string create() {
return "world";
}
// main.cpp
import <iostream>;
import <string>;
import <vector>;
import mymodule;
int main() {
std::string vec = create();
std::cout << vec << std::endl;
}
我试过(但没有实际效果):
.cpp
vs.mpp
扩展名,尽管这无关紧要- 每次编译前清除缓存(ref)
global module fragment (7)
展示位置即module; [stuff]; export module mymodule;
- 单独编译 (
-c mymodule.cpp
+-c main.cpp
) 到 link 手动(在main.cpp
上以同样的方式失败) - (重新)从函数
export
移动 - 不调用函数,只是导入(
import mymodule;
触发编译) - 从
std::vector<std::string>
切换到std::vector<int>
以查看模板的参数列表是否导致问题 - 从
std::vector<std::string>
切换到std::pair<int, int>
然后切换到std::pair<std::string, std::string>
(使用<utility>
header模块缓存)看看是否只是<vector>
对我来说坏了
看起来问题是由 <vector>
header 引起的。任何想法我怎样才能撬开 GCC 给我一些比“naaah,做不到”更好的东西?至少我可以使用 -S
(3k+ 行)生成程序集或使用 hexdump
/ objdump
来生成 gcm.cache/mymodule.gcm
并查看二进制文件,但我不确定要做什么寻找因为无用的输出。
编辑: 看起来像是架构问题?
- 使用
-m64
对模块缓存没有任何作用,仍然是 32 位 - 使用
-m32
(apk install -y g++-multilib
on 64bit)returns 相同的输出
编辑 2: 所以我在 this article 的帮助下重写了一点以使其与 Clang 12 (b978a93
) 兼容,但事实并非如此1:1 有点像屠杀(string_view
注意),但也许我没有看到更广泛的图景或缺少某些东西。
我认为我不应该包括 <string_view>
,因为那应该是自动包括的。否则,即使我编写了我的模块,我也可以从实现中每隔 #include
开始 copy-pasting,直到剩下 none,这样我就可以确保文件顺序(然后又是什么模块的点)。
// mymodule.cpp
module;
// no proper "import" available yet, so switching to the old includes
#include <string>
#include <vector>
#include <iostream>
export module mymodule;
export std::vector<std::string> create() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
return vec;
}
// need to wrap printing for a string_view for some reason
export void printme(std::string &item) {
std::cout << item << std::endl;
}
// main.cpp
// includes needed for "auto" and usage of those types
// and were needed also for print(create()) call
// so something seems broken over here
#include <vector>
#include <string>
import mymodule;
int main() {
auto vec = create();
for (std::string item : vec) {
// string_view:142:2: note: declaration of
// 'basic_string_view<_CharT, _Traits>' does not match
// std::cout << item << std::endl;
printme(item);
}
}
clang++ -std=c++20 -c mymodule.cpp -Xclang -emit-module-interface -fimplicit-modules -fimplicit-module-maps -o mymodule.pcm
clang++ -std=c++20 -fprebuilt-module-path=. -fimplicit-modules -fimplicit-module-maps mymodule.cpp main.cpp
所以这个问题似乎是 GCC 特有的,并且很可能是一个由架构切换判断的错误(hardcoding/wrong GCC 中的代码分支?)。也许值得在 >11.2.0
.
我正在使用 C++20 模块 (gcc 11.2.0) 编写共享库,并且对于 std::vector
自定义类型有相同的“错误文件数据”错误。就我而言,正如
根据您的参考,我找到了 this issue,现在有了一个临时解决方案,只需要在模块中添加这一行。
namespace std _GLIBCXX_VISIBILITY(default){}
这在我的库中与其他容器一起工作。我一直在使用编译器选项寻找合适的解决方案,但没有成功。
文件/命令
// mymodule.cpp
export module mymodule;
import <string>;
import <vector>;
namespace std _GLIBCXX_VISIBILITY(default){}
export std::vector<std::string> create() {
std::vector<std::string> vec = std::vector<std::string>{};
vec.push_back("Hello");
vec.push_back("world");
return vec;
}
// main.cpp
import <iostream>;
import <string>;
import <vector>;
import mymodule;
int main() {
std::vector<std::string> vec = create();
for (auto& item : vec) {
std::cout << item << std::endl;
}
}
g++ -fmodules-ts -std=c++20 -x c++-system-header iostream
g++ -fmodules-ts -std=c++20 -x c++-system-header string
g++ -fmodules-ts -std=c++20 -x c++-system-header vector
g++ -fmodules-ts -std=c++20 mymodule.cpp main.cpp
$ ./a.out
Hello
world
P.S。我不能评论,所以张贴为答案,希望它能提出来。