在我的项目中,我有很多枚举,需要有与枚举成员相关的其他属性和与枚举类型相关的辅助静态方法.
据我所知,这对于标准枚举类MyItem {...}是不可能的,所以对于我项目中的每个枚举类,我有一个辅助类MyItemEnum,它封装了这些辅助静态方法,并且还实例化了辅助实例本身,以便我可以访问他们的方法,以获得其他属性.
Bellow一个例子(尽可能简化,但我相信所讨论的所有功能都在那里).
MyItem.h
enum class MyItem : unsigned int {
Item1 = 1,
Item2 = 5
};
class MyItemEnum {
private:
MyItem myItem;
size_t extInfo;
MyItemEnum(const MyItem& myItem, size_t extInfo);
~MyItemEnum();
public:
static MyItemEnum Item1;
static MyItemEnum Item2;
static const MyItemEnum &get(MyItem myItem);
operator MyItem() const;
size_t getExt() const;
bool hasNext() const;
MyItem next() const;
};
Run Code Online (Sandbox Code Playgroud)
我认为意思是显而易见的,我不需要在这里提供.cpp部分...当我需要访问扩展功能时,我使用MyItem作为参数在接口和MyItemEnum中传递.
我的第一个问题是,上面的方法是否正常,或者我应该考虑一些完全不同的东西?
我的第二个问题涉及我使用constexpr尝试做的这个枚举的优化:
enum class MyItem : unsigned int {
Item1 = 1,
Item2 = 5
};
class MyItemEnum {
private:
MyItem …Run Code Online (Sandbox Code Playgroud) 当使用clang 3.5.0和-flto并使用共享库进行链接时,共享库中的调用似乎operator delete不会遵循与operator new主对象的调用相同的符号解析顺序.例:
shared.cpp:
void deleteIt(int* ptr) {
delete ptr;
}
Run Code Online (Sandbox Code Playgroud)
main.cpp:
#include <cstdlib>
#include <new>
void* operator new(size_t size) {
void* result = std::malloc(size);
if (result == nullptr) {
throw std::bad_alloc();
}
return result;
}
void operator delete(void* ptr) noexcept {
std::free(ptr);
}
void deleteIt(int* ptr);
int main() {
deleteIt(new int);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我构建它并通过valgrind运行时会发生的事情:
$ clang++ -std=c++11 -g -O3 -flto -fuse-ld=gold -fPIC -shared shared.cpp -o libshared.so
$ clang++ -std=c++11 -g -O3 …Run Code Online (Sandbox Code Playgroud) 我正在尝试系统地调试以下问题:
% gcc -fPIC -flto -o try1.o -c try1.c
% gcc -fPIC -flto -o try2.o -c try2.c
% gcc -shared -flto -fPIC -o try.so try1.o try2.o
try2.c:1:14: warning: type of 'aaaaaaaa' does not match original declaration [enabled by default]
try1.c:1:5: note: previously declared here
Run Code Online (Sandbox Code Playgroud)
在这个综合测试中,我确切地知道了问题所在- 在这里aaaaaaaa定义int,但是short在那里。在我真正的问题中,链接组合了许多对象,这些对象是复杂的构建过程的结果,而且我不知道哪两个对象包含冲突的定义。
我想通过检查每个链接的目标文件来解决它,看看每个文件中如何定义符号,并找到一对定义不匹配的文件。然后,我将跟踪构建过程,以了解它们是如何构建的,并找到根本原因。但是我不知道查看对象定义方式的方法。
我尝试了nm -A和objdump -t,但是它们没有显示符号类型/大小:
% nm -A try1.o
try1.o:00000001 C __gnu_lto_v1
try1.o:00000000 D aaaaaaaa
% nm -A try2.o
try2.o:00000001 C __gnu_lto_v1
try2.o: U aaaaaaaa …Run Code Online (Sandbox Code Playgroud) 我有编译和链接的代码。
我现在正在尝试启用链接时优化,但是添加-flto到我的编译器和链接器标志会导致链接器错误:
/usr/local/lib/libboost_thread.a(thread.o): \
In function `void boost::throw_exception<boost::bad_lexical_cast>(boost::bad_lexical_cast const&)':
thread.cpp:(.text._ZN5boost15throw_exceptionINS_16bad_lexical_castEEEvRKT_[_ZN5boost15throw_exceptionINS_16bad_lexical_castEEEvRKT_]+0x124): \
undefined reference to `vtable for boost::bad_lexical_cast'
Run Code Online (Sandbox Code Playgroud)
我添加的唯一标志是-flto.
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto" )
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -flto" )
Run Code Online (Sandbox Code Playgroud)
要清楚:
-flto应用程序构建和链接很好-flto(并且没有其他更改),应用程序无法链接上述错误是什么导致此链接器错误?
码:
#include <iostream>
#include <string>
#include <fstream>
int main(int argc, char *argv[]) {
std::string filename = "dummyfile";
std::ifstream infile(filename);
std::string line;
std::getline(infile, line);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译并链接:
g++-7 -std=c++17 -flto mycode.cpp
Run Code Online (Sandbox Code Playgroud)
结果是:
*./a.out'出错:free():无效指针:0x0000000000602200* Aborted(core dumped)
它编译并运行良好,没有-flto标志.保持-flto但改变-std=c++17到-std=c++14或-std=c++11将使其工作过.如此看来,有一些有关的组合flto和c++17.
gdb结果:
#0 0x00007ffff7a4acc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1 0x00007ffff7a4e0d8 in __GI_abort () at abort.c:89
#2 0x00007ffff7a87f24 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7ffff7b966c8 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175 …Run Code Online (Sandbox Code Playgroud) 相当大的共享库(许多模板实例化)的LTO构建需要相当长的时间(> 10分钟).现在我知道了关于库的一些事情,并且可以以对象文件的形式指定某种"黑名单",这些文件不需要一起分析(因为它们之间没有应该内联的调用),或者我可以指定应该一起分析的目标文件组.这可能是某种方式(没有拆分lib)?
是否存在检测代码是否使用-flto编译的任何方法?
示例是使用GCC(4.9.1)编译且未经调试的Linux下的经典库或可执行文件。
我未能使用MinGW-W64为Windows x86-64构建共享库-flto。这是我得到的(在Linux机器上完成编译):
# ...
x86_64-w64-mingw32-g++ -c -std=gnu++11 -fvisibility=hidden -DGLEW_STATIC -Ofast -flto -frtti -pedantic -Wall -Wextra -fexceptions -mthreads -DUNICODE -DQT_LARGEFILE_SUPPORT -I. -I'include' -I'/usr/x86_64-w64-mingw32/share/qt4/mkspecs/win32-g++-cross-x64' -o build/Point3D.o src/Point3D.cpp
x86_64-w64-mingw32-g++ -mwindows -Ofast -flto -shared -Wl,-subsystem,windows -mthreads -Wl,--out-implib,lib/libglengine.a -o lib/glengine.dll object_script.glengine.Release -lopengl32 -Wl,-Bstatic -lturbojpeg -lpng -lwebpdecoder
Cannot export _ZNSt6vectorI6StringSaIS0_EE19_M_emplace_back_auxIJRKS0_EEEvDpOT_: symbol wrong type (4 vs 3)
Cannot export _ZNSt6vectorIPN3GLE6ShaderESaIS2_EE19_M_emplace_back_auxIJRKS2_EEEvDpOT_: symbol wrong type (4 vs 3)
Cannot export _ZNSt6vectorIPN3GLE7ProgramESaIS2_EE19_M_emplace_back_auxIJRKS2_EEEvDpOT_: symbol wrong type (4 vs 3)
collect2: error: ld returned 1 exit status
Makefile.Release:211: recipe for …Run Code Online (Sandbox Code Playgroud) 我在 CMake 3.14.0 中有以下项目,它为 Visual Studio 2017 64 位生成器构建一个项目(最低版本为 3.10.0,因为其他开发人员可以拥有以前版本的 CMake,但大于 3.9.0):
cmake_minimum_required (VERSION 3.10.0)
project (data)
add_definitions (-DDATA_EXPORTS)
include_directories (${CMAKE_CURRENT_SOURCE_DIR}/..)
set (PROJECT_SRC
Player.cpp
LLA.cpp
Attitude.cpp
)
add_library (${PROJECT_NAME} SHARED ${PROJECT_SRC})
target_compile_features (${PROJECT_NAME} PUBLIC cxx_std_17)
# Enable IPO
include(CheckIPOSupported)
check_ipo_supported(RESULT iporesult)
if(iporesult)
message (STATUS "IPO supported for project ${PROJECT_NAME}")
set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
Run Code Online (Sandbox Code Playgroud)
我添加了一些命令,用于在 Visual Studio 中添加对 LTO 的支持。我已经看到我必须检查对 IPO 的支持,如果可以,我必须设置INTERPROCEDURAL_OPTIMIZATION属性,这就是我所做的
当我运行该项目时,我收到以下消息(我也在使用 vcpkg,这就是第一行的原因):
[cmake] IPO supported for project data
...
[cmake] CMake Warning (dev) at D:/Projects/vcpkg/scripts/buildsystems/vcpkg.cmake:198 …Run Code Online (Sandbox Code Playgroud)