一、Valgrind 简介
Valgrind 是一款用于内存调试、内存泄漏检测和性能分析的开源工具集。它主要用于 Linux 系统,能够检测常见的内存错误(如非法访问、未初始化内存使用)和内存泄漏问题。
常用参数:
--leak-check=full:显示内存泄漏的详细堆栈信息。--show-leak-kinds=all:显示所有类型的内存泄漏(确定、可能、间接)。--track-origins=yes:追踪未初始化变量的来源。--log-file=filename:将输出重定向到文件。
二、linux系统编程
Linux系统编程涉及直接调用Linux内核提供的系统调用和库函数,以控制硬件资源、管理进程、文件操作等。核心内容包括文件编程、多任务编程、网络编程。

如果要使用到linux系统的功能需要通过系统调用来使用到,系统调用--就是指linux系统本身提供的函数。
linux系统下,实现一个用户的应用程序两条路径:
1.直接通过系统调用直接实现
2.通过库的方式实现库--函数库--一般是别人基于linux系统调用实现的功能更丰富使用更方便的函数
(一)文件编程
1.基于库的方式实现
stdio --- standard input output//标准的输入输出函数
2.基于系统调用的方式实现
linux系统本身提供的函数
标准I0:
在linux系统下一切皆文件
文件 --- 一组相关信息的集合linux将很多东西都抽象成文件
"-"普通文件(常规文件)eg:1.txt 图片_视频音频可执行文件
"d"目录文件(directory) eg:文件夹目录 (ls -l 目录)
"c"字符设备文件(char) eg:某一个硬件鼠标,键盘,摄像头 ls -l /dev/input
"b"块设备文件(block) eg:硬盘等存储设备----512Bytes (ls -l /dev/sda)
"l"软连接文件(link) eg:相当于windows下快捷方式 (ls -l /usr/lib)//浅蓝色
"s"套接字文件(socket) eg:网络的时候会接触到主要指的是本地sockett ---进程间通信
"p"管道文件(pipe) eg:进程间通信 mkfifo pipe (ls -l pipe)
标准IO:
1.打开
fopen//file open---打开文件
2.读写
fgetc/fputc---//按字符读写
fgets/fputs---//按字符串读写
fread/fwrite---//按对象读写(二进制流读写)
3.关闭
fclose//file close
流:是对数据读写过程的抽象。
①fopen 流打开函数
#include <stdio.h>
FILE * fopen(const char *pathname, const char *mode)
功能:打开文件并关联一个流。
参数:@pathname要打开的文件的名字---字符串形式
@mode打开文件的模式
r:打开文件做读操作。(要求:文件必须存在,不存在会报错)
r+:打开文件做读写(要求:文件必须存在,不存在会报错)
w: 打开文件做只写(说明:如果文件存在,则被截断为0如果文件不存在,则创建)
w+:打开文件做读写(说明:如果文件存在,则被截断为0如果文件不存在,则创建)
a:打开文件做追加(只写)(文件存在,则定位到末尾开始写如果文件不存在,则创建)
a+:以追加方式打开文件(读写).(文件存在,写入位置定位到文件末尾;文件不存在,创建)
返回值:成功 FILE*;
FILE *--文件指针代表打开的文件流指针代表打开的文件(关联一个流);
失败NULL&errno(错误码-全局变量)
cs
#include <stdio.h>
//命令行参数./a.out 1.txt
int main(int argc,const char *argv[])
{
if(argc != 2)
{
printf("Usage:%s <filename>\n",argv[0]);
return -1;
}
FILE *ph = fopen(argv[1],"r");
if(ph == NULL)
{
perror("fail");
return -1;
}
printf("success!\n");
return 0;
}
②fgetc 读函数
int fgetc(FILE*stream);
功能:从流中获得数据(一次只能读取一个字符)
参数:@stream fopen成功打开文件后获得的流指针。
返回值:成功返回读取到的字符;
失败返回EOF(-1),当到达文件结尾也会返回EOF。
操作系统默认已经打开了三个流:
stdin---标准输入//FILE*指针//strucr_IO_FILE(键盘上ctrl + d可以产生一个EOF)
cs
#include <stdio.h>
int main(int argc, const char *argv[])
{
int ret = 0;
while((ret = fgetc(stdin)) != EOF)
{
printf("ret = %d:%c\n",ret,ret);
}
return 0;
}
stdout---标准输出
stderr---标准出错//也是个输出
③关闭文件
功能:关闭文件并断开关联的流
参数:@stream要关闭的流指针
返回值:成功0;失败EOF&&errno被设置
注意:同一个文件,只需要关闭一次
④ fputc 写函数
int fputc(int c,FILE*stream)
功能:将字符c输出到stream对应流中
参数:@c要输出的字符
@stream要输出到的流
返回值:成功输出了的字符;失败EOF。
cs
int ret = 0;
while((ret = fgetc(ph)) != EOF)
{
//printf("%c",ret);
fputc(ret,stdout);
}
fclose(ph);
⑤fgets //获取数据
char *fgets(char *s,int size,FILE*stream)
功能:从stream中读取数据:存放到s指定的空间最多读取size-1个字符
参数:@s---存放数据的空间
@size---表示要读取的字节数
@stream---表示要读取的文件流指针
返回值:成功:s ;失败:NULL。(到达文件结尾返回的也是NULL)
读取结束的条件:
1.到了EOF
2.读到了'\n';但是'\n'会被保存到s指定的空间
3.读满size-1;'\0'读取结束后,在s指定的空间中最后个字符后面加入'\0'
cs
#include <stdio.h>
int main(int argc, const char *argv[])
{
char s[100] = {1,1,1,1,1,1,1,1,1,1};
fgets(s,10,stdin);
for(int i = 0;i < 10;i++)
{
printf("s[%d] = %c:%d\n",i,s[i],s[i]);
}
printf("s= %s\n",s);
return 0;
}
练习:
cs
#cat代码
#include <stdio.h>
int main(int argc, const char *argv[])
{
if(argc != 2)
{
printf("%sfile<filename>\n",argv[0]);
return -1;
}
FILE *ph = fopen(argv[1],"r");
if(ph == NULL)
{
perror("fail");
return -1;
}
int c;
while((c = fgetc(ph)) != EOF)
{
//printf("%c",ret);
fputc(c,stdout);
}
fclose(ph);
return 0;
}
cs
#复制代码
#include <stdio.h>
int main(int argc, const char *argv[])
{
if(argc != 3)
{
printf("%sfile<filename>\n",argv[0]);
return -1;
}
FILE *ph = fopen(argv[1],"r");
FILE *fp = fopen(argv[2],"w");
if(ph == NULL)
{
perror("fail");
return -1;
}
int c;
while((c = fgetc(ph)) != EOF)
{
//printf("%c",ret);
fputc(c,fp);
}
fclose(ph);
fclose(fp);
return 0;
}