找回密码
 注册
搜索
热搜: 回贴
微赢网络技术论坛 门户 服务器 Linux/BSD 查看内容

数据管理(二)

2009-12-20 13:46| 发布者: admin| 查看: 84| 评论: 0|原作者: 夙瑶

Null指针
与MS-DOS不同,但是类似于新版本的Windows,现代的Linux系统会小心的处理读取或是写入由null指针所指向的地址,尽管实际的行为是实现相关的。
试验--访问Null指针
下面我们在memory5a.c程序中试一下当我们访问一个null指针时会发生什么情况:
#include
#include
#include
int main()
{
char *some_memory = (char *)0;
printf(“A read from null %s\n”, some_memory);
sprintf(some_memory, “A write to null\n”);
exit(EXIT_SUCCESS);
}
其输出如下:
$ ./memory5a
A read from null (null)
Segmentation fault(core dumped)
工作原理

一个printf试图打印出由一个null指针处所取得的字符串;然后sprintf试图将一个字符串写入null指针处。在这种情况下,Linux(借
助GNU
C库)忽略了此处的读取,并且只是简单的返回给我们一个包含(null)\0字符的神奇字符串。但是他并没有忽略写入操作,并且结束了这个程序。这对于追
踪程序bug是十分有用的。
如果我们再试一次,但是这次我们不使用GNU C库,我们就会发现由地址0处读取是不允许的。如下面的memory5b.c:
#include
#include
#include
int main()
{
char z = *(const char *)0;
printf(“I read from location zero\n”);
exit(EXIT_SUCCESS);
}
其输出如下:
$ ./memory5b
Segmentation fault(core dumped)
工作原理
这一次我们试着直接由地址0处读取。但是这一次在我们与内核之间并不存在GNU libc库,但是我们程序被终止了。我们应该注意到某些版本的UNIX允许由地址0处读取,但是Linux并不允许这样做。
释放内存

到现在,我们只是简单的分配内存,然后希望当程序结束时,我们所用的内存并没有丢失。幸运的是Linux内存管理系统具有可靠的能力可以保证当一个程序结
束时其所用的内存会返回给系统。然而,绝大多数的程序并不只是希望简单的分配某块内存,使用一段时间,然后退出。一个更为普遍的用法是在需要时动态使用。

态使用内存的程序应总是使用free调用释放不再使用的内存,从而将这些内存返回malloc内存管理器。这会使得单独的内存进行重新合并,并且使得
malloc库来管理内存,而不是使得程序来管理内存。如果一个运行的程序(进程)使用然后释放内存,释放的内存会保持分配给进程。然而,如果他不再被使
用,Linux内存管理器就可以将其由物理内存中换出保存到交换空间中,这对于资源的使用有一些小的影响。
#include
void free(void *ptr_to memory);
free调用只可以使用由malloc,calloc或是realloc调用所获得的内存指针来进行调用。我们很快就会遇到calloc与realloc。
试验--释放内存
此处程序名为memory6.c:
#include
#define ONE_K (1024)
int main()
{
char *some_memory;
int exit_code = EXIT_FAILURE;
some_memory = (char *)malloc(ONE_K);
if (some_memory != NULL) {
free(some_memory);
exit_code = EXIT_SUCCESS;
}
exit(exit_code);
}
工作原量
这个程序只是简单的演示了如何使用前面已分配内存的指针调用free函数。
记住一旦我们在某一个内存块上调用了free函数,那么他就不再属性于这个进程。他也不再被malloc库所管理。不要在调用free函数之后试图在此内存块上执行读写操作。
其他的内存分配函数
还有另外两个不如malloc与free这样经常使用的内存分配函数:calloc与realloc。其函数原型如下:
#include
void *calloc(size_t number_of_elements, size_t element_size);
void *realloc(void *existing_memory, size_t new_size);

管calloc分配的内存可以使用free函数调用来进行翻译,但是他却具有某些不同的参数:他为一个结构数据分配内存,并且需要元素个数以及每一个元素
的尺寸作为其参数。分配的内存会使用0进行填充,如果calloc函数调用成功,则会返回一个指向第一个元素的指针。与malloc函数类似,其后的调用
并不会返回连续的空间,所以我们不可能通过简单的再次调用calloc函数并且期望第二次调用所返回的内存添加到第一次调用的结束处,从而来扩大由
calloc所分配的内存空间。
realloc会改变前一次分配的内存块的尺寸。调用此函数时会传递一个指向由
malloc,calloc或是realloc函数所分配的内存的指针,并且根据要求调整其大小。realloc也许会需要能过移动数据来达到此目的,所
以很重要的一点就是要保证一旦内存被重新分配了,我们必须使用新的指针,而不要试图使用realloc调用以前的指针来访问内存。
另一个需要关注的问题就是如果realloc不可以调整内存,他就会返回一个空指针。这就意味着,在某些程序中,我们应避免编写类似如下的代码:
my_ptr = malloc(BLOCK_SIZE);
....
my_ptr = realloc(my_ptr, BLOCK_SIZE * 10);

果realloc函数调用失败,他就会返回一个空指针;my_ptr就会指向空;那么原始的由malloc所分配的内存就不可以使用my_ptr来访问
了。很可能我们所需要做的是首先访问由malloc所分配的新内存,然后在翻译旧内存块之前使用memcpy函数将旧内存块的数据拷贝到新内存块。一旦出
现错误,这可以使得程序重新访问存储在原始内存块中的数据,也许就是在执行程序清理的时候。







最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-30 05:25 , Processed in 0.198634 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部