关于unix下c编程的错误处理及环境变量、内存管理

错误处理

一般我们通过返回值的非法或合法表示错误,对于指针,NULL或0xffffffff表示错误。
当然还有一个全局变量errno用来表示错误编号。
char *strerror(int errnum); // 通过错误码来获取错误信息
void perror(const char *s); // 输出上一个操作的错误原因

#include <stdio.h>
#include <string.h>
#include <errno.h>

extern int errno;

int main()
{
	FILE* frp = fopen("dwqjakl","r");
	if(NULL == frp)
	{
		printf("%d\n",errno);
		printf("%s\n",strerror(errno));
		perror("fopen");
		return -1;
	}
}

输出结果为:

2
No such file or directory
fopen: No such file or directory

环境变量

操作会为每个程序分配一张环境变量表,程序对这张进行添加删除修改,是不会影响操作系统。

获取环境变量表的方式

1、声明一个二级指针 extern char** environ;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern char** environ;

void show_env(void)
{
	printf("------------环境变量表------------\n");
	for(int i=0; environ[i]; i++)
	{
		printf("%s\n",environ[i]);
	}
}

int main()
{
	show_env();
}

2、通过main函数参数获取

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc,char** argv,char** environ)
{
	printf("------------环境变量表------------\n");
	for(int i=0; environ[i]; i++)
	{
		printf("%s\n",environ[i]);
	}
}

操作环境变量表

char *getenv(const char *name);
	功能:获取环境变量的值
	name:要获取的环境变量名
	返回值:获取取的环境变量值的字符串首地址,找不返回值为NULL。

int putenv(char *string);
	功能:向环境变量表中添加环境
	string:name=value
	返回值:成功返回0,失败返回非0。
	
int setenv(const char *name, const char *value, int overwrite);
	功能:向环境变量表中添加环境变量
	name:环境变量名
	value:环境变量值
	overwrite:如果环境已经存在,它决定了是否覆盖。
		0 不覆盖
		1 覆盖
		
   int unsetenv(const char *name);
   	功能:从环境变量表中删除环境变量
   	name:要删除的环境变量名
   
   int clearenv(void);
   	功能:清空环境变量表

将PATH给PATH追加一个"."路径

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	char buf[255] = {};
	printf("%s\n",getenv("PATH"));
	strcpy(buf,getenv("PATH"));
	strcat(buf,":.");
	setenv("PATH",buf,1);
	printf("%s\n",getenv("PATH"));
}

内存管理

STL中使用的是智能指针,类似与java的垃圾回收系统,可以实现自动分配自动释放。
C++中则使用new/delete关键字来申请内存。
C中通过malloc/free函数来申请内存。
POSIX则用过brk/sbrk,这是标准操作系统提供的接口。
Linux mmap/munmap 内存的映射和取消映射
内核		kmalloc/kfree
驱动		get_set_page

通过strace命令可以看到程序的系统内存调用。

#include <stdlib.h>

int main()
{
	int *p = malloc(sizeof(int));
	free(p);
}

一个简单的申请指针的代码,通过strace来查看他的内存调用。

strace ./a.out 

execve("./a.out", ["./a.out"], [/* 64 vars */]) = 0
brk(0)                                  = 0x20d9000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0a70a15000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=166042, ...}) = 0
mmap(NULL, 166042, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0a709ec000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2107816, ...}) = 0
mmap(NULL, 3932736, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0a70434000
mprotect(0x7f0a705ea000, 2097152, PROT_NONE) = 0
mmap(0x7f0a707ea000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x7f0a707ea000
mmap(0x7f0a707f0000, 16960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0a707f0000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0a709eb000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0a709e9000
arch_prctl(ARCH_SET_FS, 0x7f0a709e9740) = 0
mprotect(0x7f0a707ea000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7f0a70a16000, 4096, PROT_READ) = 0
munmap(0x7f0a709ec000, 166042)          = 0
brk(0)                                  = 0x20d9000
brk(0x20fa000)                          = 0x20fa000
brk(0)                                  = 0x20fa000
exit_group(0)                           = ?
+++ exited with 0 +++

可以看到malloc接口,最后是通过brk接口来申请到内存的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值