Linux下C的编写和执行

2024-08-27 版权声明 我要投稿

Linux下C的编写和执行(通用4篇)

Linux下C的编写和执行 篇1

查看文件是否为二进制程序用 file 命令

[gang@www]$ file /bin/ls/bin/ls: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.4.0, dynamically linked (uses shared libs), stripped

ELF 64-bit LSB executable 表示可执行文件

Linux下C的编写和执行 篇2

对于一个C/C++程序员来说, 内存泄漏是一个常见的也是令人头疼的问题。目前已经有许多技术被研究出来以应对这个问题, 比如Smart Pointer、Garbage Collection等。其中Smart Pointer技术比较成熟, STL中已经包含支持Smart Pointer的class, 但是它的应用并不广泛, 而且也不能解决所有的问题; Garbage Collection (垃圾回收) 在Java中的应用已经比较成熟, 但是在C/C++领域的发展并不顺利。现在已经有许多工具能够帮助检验程序中是否存在内存泄漏, 找出产生问题的代码。本文介绍了一种在Linux下使用Valgrind查找内存泄漏的方法。

1 内存泄漏的定义

内存泄漏 (memory leak) 是指程序在申请获得动态内存块并使用完毕后, 没有释放所申请的动态内存就将保存动态内存地址的变量用于其它用途, 使得这些动态内存不可能再被程序使用, 也无法被操作系统回收。常说的内存泄漏一般是指堆内存的泄漏。堆内存是指程序从堆中动态分配的、任意大小的存储区, 其使用完后必须由程序释放。应用程序一般使用malloc、realloc、new等函数从堆中分配到1块内存, 使用完后, 必须调用free或delete等函数释放该内存块, 否则, 这块内存就不能被再次使用, 即造成内存泄漏。

2 内存泄漏的分类

根据发生的方式, 内存泄漏通常分为4类:

(1) 常发性内存泄漏。造成内存泄漏的代码会被多次执行, 每次代码被执行时都会导致1块内存泄漏。

(2) 偶发性内存泄漏。造成内存泄漏的代码只有在某种特定环境或操作下才会发生。常发性和偶发性是相对的。对于特定的环境, 偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。

(3) 一次性内存泄漏。造成内存泄漏的代码只会被执行1次, 或者由于算法上的缺陷, 导致总会有1块仅且只有1块内存发生泄漏。

(4) 隐式内存泄漏。程序在运行过程中不断地分配内存, 但是直到结束的时候才释放内存。确切地说这里并没有发生内存泄漏, 因为程序最终释放了所有申请的内存。但是对于一个服务器程序来说需要长时间连续不间断运行, 有时几个月甚至几年, 如果不及时释放内存可能会导致最终耗尽系统的所有内存。所以, 这类内存泄漏称为隐式内存泄漏。

3 内存泄露的危害

从用户使用角度来看少量的内存泄漏不会产生什么危害, 作为一般的用户, 根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积, 这会最终消耗尽系统所有的内存。从这个角度来说, 一次性内存泄漏并没有什么危害, 因为它不会堆积, 而隐式内存泄漏危害性则非常大, 因为较之于常发性和偶发性内存泄漏它更难被检测到。存在内存泄漏问题的程序除了会占用更多的内存外, 还会使程序的性能急剧下降。

4 内存泄漏的常发场景

(1) 指针重新被赋值

下面通过一个示例来说明重新赋值这个问题:

char *memoryArea = (char *) malloc (10*sizeof (char) ) ;

char *newArea = (char *) malloc (10*sizeof (char) ) ;

图1为内存位置赋值示意图。

如果执行如下所示的语句 (指针重新被赋值) :

memoryArea = newArea;

在上面的代码中, 将newArea 指针赋值给 memoryArea指针。结果, memoryArea以前所指向的内存位置变成了孤立的, 则无法释放, 因为没有指向该位置的指针, 这会导致10 B的内存泄漏, 如图2所示。

所以在对指针赋值前, 一定要确保内存位置不会变成孤立的。

(2) 首先释放父块

假设有一个指针memoryArea, 它指向一个 10 B的内存位置。该内存位置的第3个字节又指向某个动态分配的10 B的内存位置, 如图3 所示。

如果通过调用free来释放memoryArea, 则newArea指针所指向的内存位置无法释放, 因为已经没有指向该位置的指针。换句话说, newArea所

指向的内存位置变成孤立的, 从而导致了内存泄漏。 所以每当释放结构化的元素, 而该元素又包含指向动态分配的内存位置的指针时, 应首先遍历子内存位置 (在此例中为 newArea) , 并从那里开始释放, 然后再遍历回父节点。这里正确的实现应该是:

free (memoryArea ->newArea) ;

free (memoryArea) ;

(3) 返回值的不正确处理

有时, 某些函数会返回对动态分配的内存调用。跟踪该内存位置并正确地处理它就成了calling函数的职责。

在上面的示例中, callingFunc函数实现了对func函数的调用, 但由于未能正确处理func函数的返回地址, 结果, func函数所分配的20 B的块就丢失了, 导致了内存泄漏。

通常, 发生内存泄漏的情形多种多样, 开发人员很难从源代码中找出所有造成内存泄漏的代码, 因此, 需要寻求一种方法来自动检测内存泄漏。

5 内存泄漏的检测

Valgrind是x86架构上的工具, 只能在Linux上运行, 它允许程序员在它的环境里测试程序, 以检测未配对的malloc调用错误和其它非法使用内存 (未初始化内存) 的错误。Valgrind支持很多工具: Memcheck、Addrcheck、Cachegrind、Massif、Helgrind和Callgrind等。其中Memcheck工具可以帮助开发人员检查内存使用情况, 如果没有其它参数, Valgrind在程序结束后给出关于free和malloc总共调用次数的简报。

% valgrind --tool=memcheck program_name

=18515== malloc/free: in use at exit: 0 bytes in 0 blocks.

==18515== malloc/free: 1 allocs, 1 frees, 10 bytes allocated.

==18515== For a detailed leak analysis, rerun with: --leak-check=yes

如果程序中有内存泄漏的现象, 内存分配的数量和内存释放的数量会不一致, 这时可以加上leak-check参数重新运行程序, 这样就可以看见分配了内存但却没有释放的代码。

下面是一个简单的C程序example1.c:

#include

main ()

{

char *x = (char *) malloc (100*sizeof (char) ) ;

return 0;

}

% valgrind --tool=memcheck --leak-check=yes example1

==2330== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1

==2330== at 0x1B900DD0: malloc (vg_replace_malloc.c:131) ==2330== by 0x804840F: main (example1.c:5)

现在就可以确切地知道导致内存泄漏的是哪一行代码了。注意在编译程序时, 需要给gcc加上-g参数, 否则相关的调试信息会丢失。尽管还不知道应该在哪里释放内存, 但可根据产生内存泄漏的原因来分析。因为对每一次需要动态分配的内存, 都有一个何时分配、何时释放的使用计划, 既然已经知道导致内存泄漏的分配点, 也就基本理清了内存的使用计划, 有助于定位正确释放内存的位置。

6 结语

内存泄漏是软件开发中的一个难以定位和修正的严重错误, 由于篇幅和能力有限, 本文只对这个主题作了一个粗浅的分析。更多关于内存泄漏的主题, 比如多模块下的泄漏检测, 如何在程序运行时对内存使用情况进行分析等等, 可以继续深入研究。

摘要:文章阐述了内存泄漏的概念、分类、危害以及内存泄露的常发场景, 并给出了在Linux下使用Valgrind查找内存泄漏的方法。

关键词:内存泄漏,堆内存,Linux,Valgrind

参考文献

C和LINUX笔试面试总结 篇3

给大家分享一下我的笔试和面试经历吧!笔试主要的题型有选择题、填空题、程序填空题、程序设计题目。选择和填空题的题目主要包含以下:

C语言部分:

1.逻辑运算的短路特性(考的很多)2.++、--运算符 3.位运算

4.强制类型转换 5.程序结构控制 6.数组和指针的使用

7.结构体有关(字节对齐、位段结构体)8.文件操作

9.字符串常用相关操作(非常重要)10.递归 C++部分:

1.面向对象语言特性 2.名字空间

3.函数参数传递方式以及之间的区别 4.引用

5.构造函数与析构函数的调用顺序 6.基类成员在派生类中的可见性

7.const和static的作用(有时也会考自动类型转换和explict关键字)8.多继承(考得少)9.运算符重载

10.静态联编和动态联编 11.函数模板与类模板 12.IO常用操作

13.异常处理(考的较少)14.STL容器(非常重要,比如map内部结构是什么,map内部怎么排序)数据结构部分:

1.链表的创建和元素的插入删除以及时间复杂度 2.栈和队列的特性 3.字符串KMP匹配算法 4.二叉树的构建(考得少)5.二叉树的遍历(递归和非递归算法)6.完全二叉树节点之间的数量和序号关系(大概是5条)7.哈夫曼树构建及其编码(腾讯2014校招考题)8.数和森林的转换(考的比较少,但也比较简单,会画图即可)9.排序(直接插入、选择、冒泡、快排、Shell、二路归并(2014校招腾讯考题))10.查找(包括直接查找、折半查找、建立索引、构建散列函数)11.伙伴地址(腾讯2014校招考题)12.二叉排序树和平衡二叉树的概念 Unix部分:

1.常用Shell命令 2.Shell脚本编程 软件工程部分:

1.软件过程 2.测试类型

3.面向对象常见概念(包含与继承、覆盖/重写/重载、多态)4.UML 操作系统部分:

1.进程同步、通信、多线程 2.死锁 3.信号

4.临界区、原子锁、互斥量、管道 数据库部分:

1.关系和视图的概念;

2.关系的交、并、差运算和选择、投影、连接、除运算 3.索引及其作用

4.SQL语句基本操作(尤其是语句查询、非常重要)5.游标(作用和使用)6.事务(概念)计算机网络技术部分:

1.按照作用范围对网络的划分(WAN、LAN、MAN、PAN)2.局域网的拓扑结构 3.IP地址分类 4.子网掩码

5.TCP和UCP协议的中文名称以及数据传输特点比较 6.域名服务器及FTP工作原理

7.OSI模型七层结构及各层作用和各层使用的协议

常见程序设计题(算法居多)1. C语言字符串操作(非常重要)2. 线性结构排序(一种排序的多方法实现)3. 递归的使用 4. SQL语句设计 5. 公司内部相关

我的面试总结

面试根据各个公司的情况不同而不同,一般会分为几轮面试。技术类面试的时候 衣物不要太花哨,简单朴素整洁就好,头发一定要整齐,面试的时候一般要准备一支黑色签字笔、一张稿纸、一份简历、一份成绩单原件(必须盖过章)、一份四六级成绩单的复印件。

首先在一面的时候很可能遇到群面,即群体面试,说明你命运比较悲惨。一般是6 人一小组,一般采取刷一半留一半原则,在群体面试(以我在神州数码面试为例)中,第一轮肯定是自我介绍,在这轮面试中一定要仔细聆听他人的自我介绍的一些信息,比如来自哪个学校?学什么专业?家住哪里?因为自我介绍完毕后他很可能问你其中某个同学的已经告知大家的信息,因为他要测试你的团队合作能力,然后逐个介绍自己所做的项目,这个凭自己发挥了,最后他们会给你们设计一个任务(比如举办一场晚会),让你们群体讨论合作完成,每个人都有一个相应的角色。尤其要注意的是,一般在群面中第一个发言的和发言最少的往往就是炮灰,最可能被刷掉。然后就说单面吧,单面也是先自我介绍,自我介绍时尤其注意,时间最好不要超过3分钟,关于个人信息的就描述一下自己出生于哪个省份,来自于哪个学校(如果是个985或者211一定要说明),学什么专业,技术爱好,然后就是简述一下自己做过的项目。接下来面试官就会仔细阅读你的四六级通过情况、专业课达标情况,最后就是你的项目里面的技术细节问题,一定要如实回答,会什么写什么,不会的千万不要写。一面结束了,如果在24小时之内你没有收到下一轮面试通知,那你很可能已经被刷掉(当然还有可能因为指标太少问题,时间更长,你才能接到下一轮面试)。进入下轮面试一般情况是公司所需的技术考核,这轮面试一般来说难度是最大的,这个就靠的是你平时的基本功了,如果本轮面试通过,那么恭喜你已经有八成的几率被录取。最后一轮一般是Offer面谈,如果前面你有比较好的offer,那么你一定要要求比这个offer高出1~2万,但如果之前没有像样儿的Offer,那么你先让人力的说明Offer,如果很满意就签吧,如果不是十分满意,不要很快把三方给公司,要以学校方面或者考试等为由使出缓兵之计,尽量将时间拖延至最大,以抽出时间进行下一个公司的应聘。因为如果你把三方已签,再想签约别的公司的话,就意味着要毁约,当然违约金不可避免,况且毁约是一件相当麻烦的事情,因为现在毁约的话,在公司要经过好多的部门审核(以我实习结束办理手续为例,要经过财务部、仓库、企信办、人力资源等19个部门的签字),过程相当麻烦,这很可能让你赔了夫人又折兵。

简历制作

再说说简历制作问题吧,简历整体要模块划分。第一栏就是个人信息模块,我想强调的是把自己的名字字体放大加粗加黑一下吸引眼球,然后下面列举个人的出生地、来自学校、专业、出生年月、应聘类型(C++还是嵌入式开发)、联系方式、邮箱地址、英语级别(通过四级/六级),如果是应聘国企最好加上政治面貌,而且在四级或者六级成绩比较好的话最好列举出自己的成绩。还有如果学校是985或者211,那么在页眉加一张有校园校徽并且具有985或者211信息的图片,以提升面试官的第一印象。第二栏应该就是列举出你会使用的技术,这个很重要,列举时按照熟练程度依次往下列举,掌握最成熟的放在最前面,不会使用的千万不要去写,如果被问到但没掌握那直接就被挂掉了。列举的时候最好将关键字加粗加黑放大,让人一看便知你所掌握的技术,具体到某一个你所应聘公司所需要的技术,那么他可能就会考核你。第三栏就是你在学校所做过的项目(这个必须有,也能决定你是否会进入面试环节),项目中使用的关键技术一定要突出说明。而且尤其要注意,一般写项目不要太多,最好是两个或者是三个,最好有一个你自己独立去完成的项目(该项目不是老师带着你去做的)。第四栏就是你所在学校参加的校园活动或者你的实习经历(如果是国企,最好写多一点,否则拣最重要的三四条写)。第五栏就是个人评价,主要描述一下你的团队精神,学习能力,敬业精神即可,阐述个三四行左右即可,关于个人喜好方面的只需点到即可。

我的建议

Linux下C的编写和执行 篇4

前天正在跟前端的同事调试功能,服务器开好,模拟的玩家登录好,就在倒计时。这时突然运营的同事跑过来说要统计几个服务器玩家的一些情况,也就是需要从几个服的数据库导出部分玩家的数据。好吧,我看了一下时间,11:47。心想,跟前端调试完,去吃个饭再午休一下那就下午再给吧。没想对方来一句“就导个数据库而已,要这么久么?”,而且还是直接跟我上司说的。我嚓,好吧,我导。可问题来了,平时的统计是由php做的,批量部署这些是由运维做的。服务端完全没有对应的工具。而且服务器是在阿里云上的,数据库的用户是限制了ip段登录的,我所在的ip没法登录的。于是,只好终止调试,切ip,写sql,然后用navicat手动一个个服务器导出数据到excel。

事后想想,还是写个脚本吧,不然以后还是会被坑的。

从环境来看,数据库不能直接登录,没法直接导出。不过可以由运维提供key通过ssh登录到远程服务器再将数据导出到本地。

先配置ssh通过key登录服务器。这里略过...

然后就是通过ssh执行命令。先看一下ssh的帮助文档:

usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec][-D [bind_address:]port] [-E log_file] [-e escape_char][-F configfile] [-I pkcs11] [-i identity_file][-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec][-O ctl_cmd] [-o option] [-p port][-Q cipher | cipher-auth | mac | kex | key][-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port][-w local_tun[:remote_tun]] [user@]hostname [command]

最后一项就是执行指令的。假如远程服务器地址为180.97.33.108,开启的ssh端口为998,ssh用户名为xzc,然后想通过在远程服务器上执行命令ls,那么脚本应该这么写:

代码如下:

ssh xzc@180.97.33.108 -p 998 “ls”

如果ssh的认证key已配置好,那么会把登录后当前目录下的文件列出来,当然第一次登录会提示保存远程服务器的指纹。现在是要导出数据库的数据,那么需要把ls命令换成导出数据库的命令。

代码如下:

echo “select * from user;” | mysql xzc_db -uxzc -pxzcpwd

#或者

mysql xzc_db -uxzc -pxzcpwd -e “select * from user”

上面两命令都可以使用数据库用户xzc,密码xzcpwd从数据库xzc_db打印出user表,使用的是默认的本地数据库地址localhost,默认的端口。如果不是默认,需要指定。

登录OK了,打印也OK了,那么下一步就是导出到文件了。这在bash也就是一个 > 的事。把上面的命令拼起来就是:

代码如下:

ssh xzc@180.97.33.108 -p 998 ‘echo “select * from user;” | mysql xzc_db -uxzc -pxzcpwd‘ > user.txt

这样就把user表导出来本地的user.txt中了。注意“> user.txt”如果放到 ‘‘里则是在远程服务器执行,导出的文件在远程服务器。文件现在也有了,不过是txt,这样交给运营不太好吧。那就导出excel吧。不过遗憾的是我查了N多资料,也找不到mysql不依赖第三方插件或工具导出原生excel的方法。而navicat导出的可是货真价实的excel,如果用notepad++之类的文本工具打开是会乱码的,并且导出的文件不会有编码问题。幸好如果一个txt以tab分割的话,excel也是能认得出来的。于是把user.txt改名user.xls就可以了。但这样做的问题是excel会按自己的方式处理内容的。比如把一个很大的数字转换成科学记数法形式。这些都得手动去处理一下了。

最后,就是写成脚本批量操作了,

附上我使用的脚本一个:

#!/bin/bash# 通过ssh远程执行远程指令# 需要先部署key认证,保证ssh只需要ip、port即可连接# 如果需要和远程服务器交互,请参考ssh的-t、-tt参数# 如果需要反复登录服务器执行多条指令,请使用ssh的通道重用# 参考:en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing# 使用通道需要注意退出通道,如“ssh github.com -O exit”或者“ssh github.com -O stop”# --by coding my life#分别设置ssh用户名、数据库用户名、数据库密码、导出数据SSH_USER=‘xzc_ssh‘DB_USER=‘xzc_db‘DB_PWD=‘xzc_db_pwd123‘EXP_PATH=export_data/# 执行远程命令# $1 服务器ip# $2 ssh端口# $3 指令function exec_remote_command(){ ssh $SSH_USER@$1 -p $2 ‘$3‘}# 执行远程sql,导出数据# $1 服务器ip# $2 ssh端口# $3 指令,多个sql指令如select * from user;select * from bag;也可执行,但结果将会写到同一个文件# s4 服务器# $5 导出文件function export_remote_sql(){ echo export from $4 ... cmd=“echo ”$3“ | mysql $4 -u$DB_USER -p$DB_PWD --default-character-set=utf8” ssh $SSH_USER@$1 -p $2 “$cmd” > $EXP_PATH$4_$5 #如果要导出到远程服务器,将把 > $EXP_PATH$4_$5放到cmd中}# $1 区服名# $2 ip# $3 端口function exec_sqls(){ cat SQLS | while read sql ; dofc=${sql:0:1} if [ “#” == “$fc” ]; then #被注释的不处理continue fi #sql语句中包含空格,不能再以空格来区分。最后一个空格后的是导出的文件名 exp_file=“${sql##* }” #两个#表示正则以最大长度匹配*和一个空格(*后面的空格),截取余下的赋值给exp_file sql_cmd=“${sql%% $exp_file}” #两个%表示从右至左删除%%以后的内容 export_remote_sql $2 $3 “$sql_cmd” $1 “$exp_file” done}# 需要在当前目录下创建服务器列表文件SERVERS,格式为“数据库名 ip ssh端口”,如“xzc_game_s99 127.0.0.1 22”# 需要在当前目录下创建sql命令列表文件SQLS,格式为“sql语句 导出的文件”,如“select * from user; user.xls”# 多个sql请注意用;分开,sql必须以;结束# 文件名中不能包含空格,最终导出的文件为“数据库名_文件名”,如“xzc_game_s99_user.xls”mkdir -p $EXP_PATHcat SERVERS | while read server ; do fc=${server:0:1} if [ “#” == “$fc” ]; then #被注释的不处理 continue fi name=`echo $server|awk ‘{print $1}‘` ip=`echo $server|awk ‘{print $2}‘` port=`echo $server|awk ‘{print $3}‘` exec_sqls $name $ip $portdone

当前目录下的文件如下,其中SERVERS是服务器列表,里面指定数据库名,ip,ss端口,SQLS则指定sql指令及导出的文件名。这两个文件里以#开头的都不会处理:

xzc@xzc-HP-ProBook-4446s:~/桌面/remote_cmd$ lsremote_cmd.sh SERVERS SQLSxzc@xzc-HP-ProBook-4446s:~/桌面/remote_cmd$ cat SERVERS xzc_game_s99 120.0.0.99 6162xzc_game_s91 120.0.0.91 6162xzc_game_s92 120.0.0.92 6162xzc_game_s93 120.0.0.93 6162xzc_game_s94 120.0.0.94 6162#xzc_game_s91 120.0.0.91 6162xzc@xzc-HP-ProBook-4446s:~/桌面/remote_cmd$ cat SQLS #select * money from money; money.xlsselect * from user; user.xlsxzc@xzc-HP-ProBook-4446s:~/桌面/remote_cmd$

上一篇:昌吉学院2014年招生就业工作总结下一篇:中医大毕业论文