记录一个C++编译生成的可执行文件没有进入到main方法中就发生段错误的问题

问题描述

今天在使用C++编写代码生成可执行文件时,发现一个之前没有遇到过的问题。具体地,编译生成的可执行文件,在都还没有进入main函数中前就发生了段错误运行崩溃的情况,使用gdb进入调试模式,也没有其他有效的提示信息,只有以下类似的输出信息:

#0  0x0000000000000001 in ?? ()
#1  0x00007fffffffe6fa in ?? ()
#2  0x0000000000000000 in ?? ()

网上搜相关问题,有的说是静态变量静态资源相关的,还有的说是库链接的问题,但我的工程出现的情况跟这两种应该都不符合

问题复现

  • 复现文件
    现使用以下简单的代码复现下该问题

    // test.cpp
    
    #include <iostream>
    
    int main() {
        std::cout << "Test." << std::endl;
        return 0;
    }
    

    代码很简单,man函数中只做了一个标准输出的操作。对应地,写一个简单的CMakeLists.txt

    # CMakeLists.txt
    
    cmake_minimum_required(VERSION 2.8)
    
    set(CMAKE_CXX_FLAGS "$ENV{CMAKE_CXX_FLAGS} -std=c++14 -g -O0 -shared -fPIC")
    
    add_executable(test test.cpp)
    

    在CMakeList中,指明了使用C++14,为了可以调试,添加了编译选项-g-O0,还有两个编译选项-shared-fPIC后面介绍

  • 编译生成可执行文件
    依次执行以下命令编译 & 生成可执行文件test

    mkdir build && cd build && cmake .. && make
    

    这一步没啥问题,编译期间也没有报啥错误,生成了可执行文件test编译&生成可执行文件

  • 运行可执行文件

    一切正常的话,会在终端输出Test.,但是实际运行的时候,发现直接发生了段错误,甚至都没有进入main函数中,使用gdb调试也没发现有效的特别的提示信息
    运行崩溃
    但是如果我直接使用g++工具编译,又发现可执行文件是可正常执行的

    g++ -std=c++14 -o test ../test.cpp
    

    注意到使用g++编译时,除了指定C++14,没有添加其他编译选项,说明问题出在了编译选项上。
    观察上面添加的所有编译选项,-g-O0都是比较常规的选项,不会出现啥问题,那出问题的选项就可能出在了-shared-fPIC选项上。CMakeLists.txt中去掉这两个编译选项,成功编译并执行

    cmake_minimum_required(VERSION 2.8)
    
    set(CMAKE_CXX_FLAGS "$ENV{CMAKE_CXX_FLAGS} -std=c++14 -g -O0")
    add_executable(test test.cpp)
    

    请添加图片描述

原因分析

生成可执行文件的CMakeLists.txt我是拷贝自生成动态库的文件夹中,而动态库生成时为了生成与位置无关的代码,达到真正意义上的代码共享。生成与位置无关的代码的动态库时,需要在编译前添加编译选项-shared·-fPIC
但当将-shared·-fPIC选项用于编译可执行文件时,编译器将会生成一个与可执行文件不兼容的输出文件,其中包含了共享库的相关信息。当尝试运行这个输出文件时,操作系统会遇到不符合可执行文件格式的数据,从而导致运行时错误和崩溃。
更多-shared·-fPIC选项相关信息,可自行网上搜索相关资料,这里不在多说明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值