首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么gcc在调用"main"后会在程序中放置"暂停"指令?

在程序中放置"暂停"指令是为了防止程序在执行完 "main" 函数后立即退出,从而给用户提供足够的时间观察程序的输出结果。在 C 语言中,当 "main" 函数执行完毕后,程序会自动返回 0,表示程序已成功执行。然而,如果没有额外的暂停指令,程序将立即退出,用户可能无法看到输出结果。

在 GCC(GNU Compiler Collection)中,"暂停"指令通常是通过在 "main" 函数之后添加 "return 0;" 语句实现的。这告诉编译器在程序执行完毕后,将控制权交还给操作系统,同时返回一个表示程序成功执行的状态码。

例如,一个简单的 C 语言程序可能如下所示:

代码语言:c
复制
#include<stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

在这个例子中,"return 0;" 语句在 "main" 函数之后,确保程序在执行完 "main" 函数后会暂停一段时间,以便用户观察输出结果。

总之,GCC 在 "main" 函数之后添加 "暂停" 指令是为了确保用户能够观察到程序的输出结果,同时也提供了一种方便的方式来通知操作系统程序已成功执行。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

【Linux】进程状态

举例 有时候电脑卡,是因为开启了太多软件,为什么启动太多程序会卡呢?.../mytest执行可执行程序 查看进程 赋值SSH渠道生成终端2 保证终端1的mytest运行的情况下,终端2输入指令 ps axj | head -1 && ps axj |.../mytest运行,并输入10 10 保证终端1的mytest运行的情况下,终端2再次输入指令 ps axj | head -1 && ps axj | grep mytest.../mytest 暂停进程,又继续进程,当前进程状态 为S,不带加号了 终端1使用ctrl c,程序不停止了 进程状态带+,进程是在前台运行的,可以使用ctrl c 终止 进程状态不带+...再次使用指令查询进程,发现子进程为僵尸状态,父进程为S+ 僵尸状态危害 父子进程,若父进程一直不读取,子进程就会处于Z状态 父子进程,若子进程一直处于僵尸状态(即退出子进程,但不回收子进程),就会在内存中一直保留该进程

6.1K30

基础理论

[PWN][基础篇]基础理论 1、相关知识 2、栈帧 3、实例教学 1、相关知识 溢出概念:计算机,当要表示的数据超出计算机所使用的的数据表示范围时,产生了数据的溢出 产生的原因: 1、使用了非类型安全的语言...PWN常用的寄存器,ESP,EBP,EIP ESP:栈顶指针,push和pop时会有变化 EBP:栈底指针,用来索引确定函数参数或者局部变量的位置(经常访问局部变量) EIP:用来存储即将执行的程序指令的地址...常用汇编指令 mov pop 弹栈 add/sub 加减 push 压栈 lea 取地址 call 调用函数 2、栈帧 从下向上,大地址到小地址 栈帧就是一个函数的执行环境 函数参数...-o 的空格的名称就是输出的文件的名称。例如我这里 -o 是 test,就是说 gcc 会在编译成功我的当前目录下生成一个叫 test 的可执行文件。...程序遇到断电再次暂停执行;如果没有断点,就会一直执行到结束。

10010

Linux下GDB调试指令总结

这次主要介绍GDB指令,其他编译方法和指令请自行上网查询! 启动gdb,可以进入到交互模式,通过以下命令对程序完成调试工作!...g++ -g -std=c++11 main.cpp gdb a.out 常用的指令如下: 01 运行指令: run(简写r): 运行程序,当遇到断点程序会在断点处停止运行,等待用户输入下一步命令...call 函数(参数):调用程序可见的函数,并传递“参数”,如:call gdb_test(55) quit(简写q) : 退出gdb 02 设置断点: break n (简写b n):第n行处设置断点...gdb_test() 函数 print gdb_test(a):将以变量 a 作为参数调用 gdb_test() 函数 display 表达式:单步运行时将非常有用,使用display命令设置一个表达式...,它将在每次单步进行指令,紧接着输出被设置的表达式及值。

4.5K20

STM32高级开发——链接器与启动文件

还有就是我们样例工程启动的文件为什么是自己编写的,它又怎样做到将程序入口引导到main函数上,那么在这篇我们就来深入的讨论下这两个话题。...工具链链接器的用法 实际,链接器的执行程序实际上是arm-none-eabi-ld这个文件,但是我再实际的编写过程遇到.c和.cpp文件混合的工程,ld会在链接过程中报错。...而对此官方的说明是推荐使用arm-none-eabi-gcc指令来链接工程,它会自动的调用ld程序且不会出现上面这种情况,所以接下来我们都是以arm-none-eabi-gcc指令来介绍链接器工作的。...这里就比较高深了,51单片机我们知道最后在生成代码51单片机内存中会有如 code、xdata、data的区段,来讲代码执行部分、变量部分等分区块放置,而.ld就是一种链接器使用的规则性文件,他告诉链接器单片机系统的...(); } 启动函数我们可以清晰地看到,最后一步,单片机的程序被转入到了main函数的入口,那么执行main函数之前,C语言,和内联汇编程序干了什么呢?

82430

【技术分享】C语言基础

二☞ C语言程序结构 C 程序主要包括以下部分: 预处理器指令 函数 变量 语句 & 表达式 注释 实例1: gcc test1.c test2.c -o main.out#include...\n”); return 0; } 解析: 程序的第一行 #include 是预处理器指令,告诉 C 编译器实际编译之前要包含 stdio.h 文件。...下一行 int main() 是主函数,程序从这里开始执行。 下一行 /*…*/ 将会被编译器忽略,这里放置程序的注释内容。它们被称为程序的注释。...下一行 printf(…) 是 C 另一个可用的函数,会在屏幕上显示消息 “Hello, World!”。 下一行 return 0; 终止 main() 函数,并返回值 0。...gcc hello.c ./a.out Hello, World! 请确保您的路径已包含 gcc 编译器,并确保包含源文件 hello.c 的目录运行它。

55710

gdb调试常用指令及案例讲解

Linux 环境软件开发,GDB 是主要的调试工具,用来调试 C 和 C++ 程序(也支持 go 等其他语言)。 一、常用指令 -g: 使用该参数编译可以执行文件,得到调试表。 gdb ....run/r: 运行程序 n/next: 下一条指令(会越过函数) s/step: 下一条指令(会进入函数) p/print: p i 查看变量的值。...continue:继续执行断点后续指令。 finish:结束当前函数调用。 quit:退出 gdb 当前调试。...break/b n 第 n 行设置断点,断点那一行不会执行 run/r 运行程序 接下来按 next/n/step/s 继续向下执行 next/n :下一个,调用函数就跑 step...也就是说,使用 1 次 print 命令只能查看 1 次某个变量或表达式的值,而同样使用 1 次 display 命令,每次程序暂停执行时都会自动打印出目标变量或表达式的值。

6K30

程序的机器级表示

指令操作数的寻址 大多数指令有一个或者多个操作数,指示该操作的元数据,以及放置目标的位置。x86-64支持多种操作数格式,源数据可以以常数形式给出,或是从寄存器或者内存读出。...1.2汇编指令 数据传送指令:将数据从一个位置复制到另一个位置的指令。 ? S表示源操作指定的值是一个立即数,存储寄存器或者内存。...然后,可以程序不同的地方调用这个函数。...转移控制的实现需要上面两条汇编指令的支持。1.3.1也提到啦,P调用个过程Q,执行call Q指令,该指令会把调用过程的下一条指令A保存在P的栈帧,并把PC寄存器设置为Q的起始位置。...经过函数的调用,可能会改变参数寄存器里面的值,当函数调用结束让,调用函数使用改变的寄存器的值是不正确的,所以调用的函数采用了这种机制,就是将寄存器的值先保存在,调用者的栈帧,在被调用者返回前,会通过栈帧里的数据回复寄存器里面的值

62910

Rust编译过程讲解与环境准备

通常可执行文件、目标文件、静态链接库(Linux的.a,Windows的.obj)和动态链接库(Linux的.so,Windows的DLL)都是ELF格式的文件ELF文件主要包含程序指令程序数据ELF...段表描述了各个段文件的偏移等信息。...连接器后续极有可能也会使用llvm提供的连接器,目前还是使用mvsc或者GNU的连接器,这也是为什么安装Rust时,需要单独安装vs环境或者gcc环境的原因。...Rust使用了它们提供的**连接器**,其实还有第三种选择就是LLVM,我认为Rust最终会在各个平台使用LLVM的**连接器**来取代目前的GNU和MSVC的地位,因为rust编译器汇编阶段使用的就是...参考和拓展* 《程序员的自我修养》2.1小节* rust语言自举,为什么还需要GNU 和 MSVC?* 为什么go仅仅160M的安装包就可以编译程序

45610

开篇:预备知识---2

所以编译器链接过程需要寻找对应函数的实现库文件并将其加入调用了该函数的源程序编译得到的 .o 文件。...在这里链接器不需要寻找该函数的实现库文件,因为我们 hello.c 源程序文件main 函数并没有调用这个 maxx 函数,所以此时链接过程只需要将之前的 hello.o 文件中加入必要的系统启动代码即可以生成可执行文件...既然我们在上面 custom2.o 实现了 minn 函数,那么我们就可以程序main 函数调用 minn 函数了。... Linux 系统下,GCC 预处理时默认会在 /usr/include 文件夹搜索使用到的头文件,链接时会在 /usr/lib 文件夹搜索要链接的库文件,Windows 下为 MinGW 安装目录的...编译器默认会在 /usr/include 和 /usr/lib 搜索头文件和库,使用这个选项将在 xxx/usr/include 和 xxx/usr/lib 目录搜索。

75620

Linux系统调用原理

system_call 过程获取 eax 寄存器的值,然后通过 eax 寄存器的值找到要调用的 系统调用 入口,并且进行调用调用完成,系统调用 会把返回值保存到 eax 寄存器。...Linux 使用寄存器来传递参数,参数与寄存器的关系如下: 第1个参数放置 ebx 寄存器。 第2个参数放置 ecx 寄存器。 第3个参数放置 edx 寄存器。...第4个参数放置 esi 寄存器。 第5个参数放置 edi 寄存器。 第6个参数放置 ebp 寄存器。...而 Linux 进入中断处理程序时,会把这些寄存器的值保存到内核栈,这样 系统调用 就能通过内核栈来获取到参数。...))) 就是告诉 GCC 所有参数都从栈读取,而 Linux 进入中断处理上下文时,会把 ebx、ecx、edx、esi、edi、ebp 寄存器的值保存到内核栈,那么 系统调用 就可以从内核栈获取到参数的值

4.2K30

S3C2440③ | GPIO实验

4.C程序访问寄存器控制LED 4.1.运行C程序的前提——启动文件 C语言入口函数是main()函数,main函数由启动文件(刚上电时执行的汇编程序)来调用调用时会进行压栈操作,调用完毕进行出栈操作...,所以需要设置好栈顶指针SP; main函数调用完毕返回启动文件调用处。...main函数,保存返回地址,转入C程序 BL main @ main函数返回,程序暂停 halt: B halt 4.2.编写C程序——指针+位操作 int main(...S3C2440这颗处理器方面,掌握了: 如何控制S3C2440的GPIO引脚:输出高低电平和检测外部输入电平(GPFCON寄存器和GPFDAT寄存器) 5条常用的ARM汇编指令:MOV、LDR、STR...C语言方面,掌握了: 启动文件中汇编是如何转入C语言的:BL调用main函数; 调用函数需要大量的使用栈,体现出启动时设置栈顶指针SP的重要性; 使用C语言指针访问寄存器,使用C语言位操作语法改变寄存器数据

1.1K30

go语言调度器源代码情景分析之七:函数调用过程

n: %d\n", n); //屏幕输出 n 的值 return 0; } 用gcc编译这个程序得到可执行程序call,然后使用gdb调试。...gdb我们通过disass main反汇编main函数找到main的第一条指令所在的地址为0x0000000000400540,然后使用b *0x0000000000400540该地址下一个断点并运行程序...,如果不恢复原样,main函数返回调用者使用rbp寄存器时就会有问题,因为执行调用者的代码时rbp本应该指向调用者的栈但现在却指向了main函数的栈。...汇编指令一节我们介绍过,执行push指令会修改rsp寄存器的值,但它并不会修改rip寄存器,为什么这里rip也变了呢?...leaveq指令上面的一条指令mov $0x0, %eax的作用在于把main函数的返回值0放在eax寄存器,等main返回调用main函数的函数可以拿到这个返回值。

1.3K30

C++静态链接

init该段里面保存的是可执行指令,它构成了进程的初始化代码。因此,当一个程序开始运行时,main函数被调用之前,Gibc的初始化部分安排执行这个段的的代码。 fini该段保存着进程终止代码指令。...因此,当一个程序main函数正常退出时,Glib会安排执行这个段的代码 这两个段init和fini的存在有着特别的目的,如果一个函数放到init段,main函数执行前系统就会执行它。...同理,假如一个函数放到nt段,main函数返回该函数就会被执行。利用这两个特性,C+的全局构造和析构函数就由此实现。我们将在第11章作详细介绍。...但实际上prnt在被调用过程,这些关于参数和堆栈分布的细节不同的机器上肯定是不一样的,甚至调用printf的指令也是不一样的(x86是call指令,MPIS是jai指令),这就是说,API相同并不表示...的问题,由于现实的因素,这个问题还会长期地存在,这也是为什么有这么多像我们这样的程序员能够存在的原因。

1.6K10

雪城大学信息安全讲义 4.3~4.4

但是,还是没有那么简单:许多操作系统,例如 Linux,将代码保存到栈,因此需要可执行的栈。例如,Linux 为了处理信号,需要在用户栈中放置代码序列。这个序列会在处理信号时执行。...你可以编写程序起始于0x00932030的内存搜索字符串。...: %d\n", x); } int main() { foo(1); return 0; } 我们可以使用gcc -S foobar.c来将这个程序编译为汇编代码。...16 行:leave:这个指令隐式执行两条指令早期 x86 发行版它是一个宏,但是后来做成了一个指令): mov %ebp, %esp pop %ebp 第一条语句释放了为函数分配的栈空间,之后跳到了返回地址...4.4 /bin/bash的保护 如果/bin/sh指向了/bin/bash,即使我们可以权限的 Set-UID 程序调用 Shell,我们也不能获得 Root 权限。

51630

Linux内核调试技术——kprobe使用与实现(一)

首先kprobe是最基本的探测方式,是实现两种的基础,它可以在任意的位置放置探测点(就连函数内部的某条指令处也可以),它提供了探测点的调用前、调用后和内存访问出错3种回调方式,分别是pre_handler...、post_handler和fault_handler,其中pre_handler函数将在被探测指令被执行前回调,post_handler会在被探测指令执行完毕回调(注意不是被探测函数),fault_handler...因此不论何种情况下,回调函数不要调用会放弃CPU的函数(如信号量、mutex锁等); 8、kretprobe通过替换返回地址为预定义的trampoline的地址来实现,因此栈回溯和gcc内嵌函数_...架构则会设置单步调试flag并回到异常触发前的流程执行; 4、单步执行完成,kprobe执行用户注册的post_handler回调函数; 5、最后,执行流程回到被探测指令之后的正常流程继续执行。...模块的卸载函数调用unregister_kprobe函数卸载kp探测点。 ?

3.7K21

makefile终极奥义

gcc -c main.c #伪指令 .PHONY:clean clean: rm -f sub.o mult.o div.o add.o main.o app 执行make命令看一下效果,很nice...那就要说说 make 是如何工作的 make是如何工作的 默认的方式下,也就是我们只输入 make 命令。那么, make会在当前目录下找名字叫“Makefile”或“makefile”的文件。...如果 edit 所依赖的 .o 文件也不存在,那么make会在当前文件找目标为 .o 文件的依赖性,如果找到则再根据那一个规则生成 .o 文件。...OBJ:=main.o #定义变量 #引用变量 ${OBJ} #使用变量 $(OBJ) #推荐使用 除了自己定义的变量之外makefile还提供了预定义的变量 隐含规则的命令,基本上都是使用了一些预先设置的变量...你可以在你的makefile改变这些变量的值,或是make的命令行传入这些值,或是在你的环境变量设置这些值 命令的变量 变量 默认命令 意义 AR 默认命令是 ar 函数库打包程序

1.3K30

Linux从入门到精通(九)——Linux编程

Linux编程 1. vi的工作方式 三种方式:命令方式、插入方式、末行方式 命令方式:用户一进入vi就进入命令方式,该模式任何键入的字符都被看成vi的命令,键入立即执行。...系统利用 gcc 命令来执行 C 语言程序,利用 g++ 命令来执行 C++ 程序。.../test.c #include //这个是/usr/lib找的 #include "mytest.h" //这个是在当前目录找的 int main(){ mytest();...\n"); } 【例2】 静态库文件方式调用: ./test.c #include int main(){ Mytest(); printf("hello!...6.1 gdb 基本用法 ​ 需要调试的程序,在编译时要使用调试选项。默认的情况下,调试符号不会编译到程序。调试之后,不需要重新编译程序

2K30

ege安装教程(第二银河配置要求)

(这里面是VS各个版本的库,如果多于1个,属于更新旧版本的遗留,小版本号的可以删了) include目录的内容 ③ 打开EGE安装包 将EGE安装包的include目录的所有文件...(如果编译出错,检查一下文件放置位置是否正确,或是安装了多个VS,或是放置到VS的旧版本文件夹) VS2019去掉控制台   如果VS2019总是自动跳出控制台,则需要设置一下 项目属性 设置一下...: D:\Dev-cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2 libgraphics64.a 放置的目录 (2) 将EGE安装包的32...解压 下载完成, 找个好点的位置,新建一个目录(别随便乱放),再解压到里面,就可以了。 比如,我 D盘根目录 新建了 mingw-w64 文件夹,然后解压到里面。...的 libgraphics.a文件 放置位置参考路径( E:\C-Free5\mingw\lib ) 项目的配置 打开C-Free, 选择新建工程 选择控制台程序, 工程名称随意(这里取

6.6K21

用图文带你彻底弄懂GDB调试原理

一、前言 这篇文章来聊聊大名鼎鼎的GDB,它的豪门背景咱就不提了,和它的兄弟GCC一样是含着金钥匙出生的,GNU的家族的地位不可撼动。...我们都知道,使用gcc编译时,可以使用-g选项可执行文件嵌入更多的调试信息,那么具体嵌入了哪些调试信息?这些调试信息是如何与二进制的指令之间进行相互交互?...此时gdb进程会发送SIGSTO信号给子进程B,子进程B接收到SIGSTOP信号,就会暂停执行进入TASK_STOPED状态,表示自己准备好被调试了。 ?...然后,调试窗口继续输入执行指令“run”(一直执行,直到遇到断点就暂停),汇编代码PC指针(一个内部指针,指向即将执行的那行代码)执行第10行时,发现是INT3指令,于是操作系统就发送一个SIGTRAP...从我们调试者角度看,就是被调试程序第5行断点处暂停了下来,此时我们可以继续输入其他调试指令来debug,比如:查看变量值、查看堆栈信息、修改局部变量的值等等。

5.2K53

__asm__ volatile 之 C语言嵌入式汇编

对于movz指令也一样。比如指令“movsbl %al, %edx”意味着将al寄存器的内容进行符号扩展后放置到edx寄存器。...调用和跳转指令 段内调用和跳转指令为"call","ret"和"jmp",段间调用和跳转指令为"lcall","lret"和"ljmp"。...然后被GCC编译的结果: $ cat example5.c// 本例,变量sh被作为一个内存输入int main(int __argc, char* __argv[]) { char* sh = (...通用约束g是一个非常灵活的约束,当程序员认为一个C/C++表达式实际的操作,究竟使用寄存器方式,还是使用内存方式或立即数方式并无所谓时,或者程序员想实现一个灵活的模板,让GCC可以根据不同的C/C+...ListGCC会通过movl %eax, address_of_out这条指令将%eax的内容放置到Output变量__out

12.1K44
领券