不以main为入口的函数
先看一段程序
#include <stdio.h> void test() { printf("Hello Word!\n"); return 0; }
没有main函数,编译一定不会通过,在gcc下编译会提示以下信息:
/usr/lib/gcc/i686-linux-gnu/4.7/../../../i386-linux-gnu/crt1.o:在函数‘_start’中:
(.text+0x18):对‘main’未定义的引用
collect2: 错误: ld 返回 1
可以看到错误信息提示,提到了一个“crt1.o”这个文件,其中crt是“C runtime library”的缩写,其含义是“C运时库”。
C运行时库除了给我们提供必要的库函数调用(如memcpy、printf、malloc等)之外,它提供的另一个最重要的功能是为应用程序添加启动函数。C运行时库启动函数的主要功能为进行程序的初始化,对全局变量进行赋初值,加载用户程序的入口函数。
从给出的错误提示信息中还可以得知,在crt1.o中,有一个名为“_start”的函数。现在网上找到一份crt1.o的伪代码:
section .text: __start: : init stack; init heap; open stdin; open stdout; open stderr; : push argv; push argc; call _main; (调用 main) : destory heap; close stdin; close stdout; close stderr; : call __exit;
从伪代码可以看出,在这个_start函数中,调用了main函数。那么我们可不可以用什么手段,去修改入口函数,把入口函数改成test函数呢?
gcc test.c -etest -nostartfiles
其中-e选项为修改函数的入口地址,可惜在网上和man手册里都没有找到有关-e这个选项的解释,只搜索到了-E这个选项。问了好多人才明白原来-e指的 就是entrance。这里把entrance指定为test函数。
-nostartfiles选项的作用是通知编译器不自动加入启动函数以及别的库级 别的初始化,这样就不会调用到crt1.o中的_start函数。
此时,编译通过。可是执行程序,可以成功打印出Hello Word!字样,但是却会提示“段错误”。
Hello Word!
段错误
原来,在编译的时候加上了-nostartfiles这个选项的同时,使得最后的return语句不能正常执行。解决方案是,把程序最后的return语句改成exit语句,让exit语句来做最后的“善后工作”。
#include <stdio.h> void test() { printf("Hello Word\n"); exit(); }
没有任何错误。
还有两种方法。。。
方法一:
#include <stdio.h> #define start main int start() { printf("Hello Word\n"); ; }
#include <stdio.h> #define start m##a##i##n int start() { printf("Hello Word\n"); ; }
方法二:
_start函数
_start函数是C程序的入口函数,会调用main函数。在调用main函数之前,会先执行_start函数分配必要的资源,然后再调用main函数。但是在用gcc编译程序时可以使用-nostartfiles选项来重写_start函数。示例程序如下:
#include <stdio.h> #include <stdlib.h> _start(void) { printf("Hello Word\n"); exit(); }
编译指令:
gcc -nostartfiles _start.c -o main.out
反汇编生成的执行程序
a. Disassembly of section .plt: <puts@plt-0x10>: : ff ea pushq <_GLOBAL_OFFSET_TABLE_+0x8> : ff ec jmpq * <_GLOBAL_OFFSET_TABLE_+0x10> 40032c: 0f 1f nopl 0x0(%rax) <puts@plt>: : ff ea jmpq * <_GLOBAL_OFFSET_TABLE_+0x18> : pushq $0x0 40033b: e9 e0 ff ff ff jmpq <puts@plt-0x10> <exit@plt>: : ff e2 jmpq * <_GLOBAL_OFFSET_TABLE_+0x20> : pushq $0x1 40034b: e9 d0 ff ff ff jmpq <puts@plt-0x10> Disassembly of section .text: <_start>: : push %rbp : e5 mov %rsp,%rbp : bf mov $0x400368,%edi : e8 d2 ff ff ff callq <puts@plt> 40035e: bf mov $0x0,%edi : e8 d8 ff ff ff callq exit@plt
不以main为入口的函数的更多相关文章
- 探秘varian:优雅的发布部署程序
上一篇文章<记一次诡异的故障排查经历>中有介绍到我们的部署程序varian,文章发布后有小伙伴对varian很感兴趣,今天就简单的介绍一下我们的varian,揭开她神秘的面纱~ 什么是va ...
- Qt Windows下链接子系统与入口函数(终结版)(可同时存在main和WinMain函数)
Qt Windows下链接子系统与入口函数(终结版) 转载自:http://blog.csdn.net/dbzhang800/article/details/6358996 能力所限,本讨论仅局限于M ...
- C++改变编程入口为main函数
1, 你用vc建了一个控制台程序,它的入口函数应该是main, 而你使用了WinMain. 2. 你用vc打开了一个.c/.cpp 文件,然后直接编译这个文件,这个文件中使用了WinMian而不是m ...
- java main函数不执行?
今天脑袋短路,对于这个问题纠结了好久.这个问题具体是这样的: public class test { public static void main(String[] args) { test2 t ...
- Java面向对象 Main函数 静态的应用 单例设计模式
Java面向对象 Main函数 静态的应用与单例设计模式 知识概要 (1)Main函数的细解 (2)静态的应用,静态变量,静态代码块,静态函数 (3)单例设计模式 1.M ...
- 通过启动函数定位main()函数
如下,通过vc6.0编写一个hello world程序.尝试结合汇编代码.分析启动函数找到main函数. 在printf(xxx)插入断点,调试执行.如下,在堆栈窗口中可见main()下的一个 ...
- java里面main函数为什么要用static修饰
这学期刚开java,因为之前只写过C++和Python没接触过java,有些写法挺不习惯的,今天写完一个程序,run的时候发现提示the selection can't be launched.... ...
- 程序入口函数和glibc及C++全局构造和析构
分类: CRT Machnasim 2011-06-15 17:45 144人阅读 评论(0) 收藏 举报 c++汇编linuxlist语言编译器 1,程序入口函数和初始化 操作系统在装载可执行文件后 ...
- 重新认识Java中的程序入口即主函数各组成部分
主函数各组成部分深入理解 public static void main(String[] agrs) 主函数:是一个特殊的函数,作为程序的入口,可以被JVM调用 主函数的定义: public:代表着 ...
随机推荐
- Broken pipe错误原因
这个异常是由于以下几个原因造成. 1.客户端再发起请求后没有等服务器端相应完,点击了stop按钮,导致服务器端接收到取消请求. 通常情况下是不会有这么无聊的用户,出现这种情况可能是由于用户提交了 ...
- MySQL事务之-2
在上一篇中我们提到了MySQL的事务特性,这一片主要讲述事务的实现. 事务的隔离性由锁来实现.原子性,一致性,持久性通过数据库的redo和undo log来实现. redo恢复提交事务修改页的操作,而 ...
- Python3:sqlalchemy对sybase数据库操作,非sql语句
Python3:sqlalchemy对sybase数据库操作,非sql语句 # python3 # author lizm # datetime 2018-02-01 10:00:00 # -*- c ...
- Spring Data JPA 关系映射(一对一,一对多,多对多 )
CascadeType.REMOVE 级联删除操作,删除当前实体时,与它有映射关系的实体也会跟着被删除.CascadeType.MERGE 级联更新(合并)操作,当Student中的数据改变,会相应地 ...
- MSSQL 重建索引(在线重建、控制最大处理器数 、MAXDOP )
一.什么情况下需要重建索引 1.碎片过多(参考值:>20%) 索引碎片如何产生,请移步至< T-SQL查询高级—SQL Server索引中的碎片和填充因子> 2.填充度过低(参考值: ...
- eclipse中下载maven插件解决办法
https://blog.csdn.net/qq_30546099/article/details/71195446 解决Eclipse Maven插件的最佳方案 https://www.cnblog ...
- Learn Rails5.2- ActiveRecord: Migration , spring的使用(不兼容的解决办法)
偶然一次: 运行rails generate停止不动,网上查找答案,可能是bundle update 之后 spring 版本变化了,和正在运行的 spring 实例不兼容. Spring导致的同样的 ...
- Leetcode 53
//经典class Solution { public: int maxSubArray(vector<int>& nums) { ; int maxsum = -INT_MAX; ...
- ASP.NET常用的指令
指令的类型 指令 说明 Application 配置全局应用程序类 Assembly 注册用在Web窗体中的程序集.建议不使用此指令.而是NuGet. Control 配置用户控件 Implement ...
- HDU 4751 Divide Groups (2-SAT)
题意 给定一个有向图,问是否能够分成两个有向完全图. 思路 裸的2-sat--我们设一个完全图为0,另一个完全图为1,对于一个点对(u, v),如果u.v不是双向连通则它们两个不能在一组,即u和v至少 ...