最近写了个代码,被日本客户指出来有问题,对此做了一项研究。
我最开始的时候写的是:
char *pointer = NULL;
pointer = “string”;
printf(“%s\n”, pointer);
日本客户指出,pointer当前没有分配空间,给它赋值是不规范的操作。
其实这个客户说的也不对,并不是没有分配空间,这个指针变量是有空间的,他的内存大小就是指针变量的大小。第二句话里,将一个字符串常量的地址赋值给了这个指针变量。如果使用时仅仅是用来做打印,那么不会有任何问题。
真正的问题在于,此时如果想修改pointer中的值,就会导致Segmentation fault (core dumped)。
对此,进行进一步的研究与分析:
首先写了一个demo:
#include<stdio.h>
#include<string.h>
int main()
{
char *pointer_1 = NULL;
char pointer_2[20] = {0};
char pointer_3[] = "string_init";
pointer_1 = "string_init";
//pointer_2 = pointer_3;
strcpy(pointer_2, pointer_3);
printf("pointer_1: %s, %p\n", pointer_1, pointer_1);
printf("pointer_2: %s, %p\n", pointer_2, pointer_2);
printf("pointer_3: %s, %p\n", pointer_3, pointer_3);
printf("%d\n", *pointer_1);
printf("%d\n", *pointer_2);
printf("%d\n", *pointer_3);
//*pointer_1 = 83;
*pointer_2 = 83;
*pointer_3 = 84;
printf("%d\n", *pointer_1);
printf("%d\n", *pointer_2);
printf("%d\n", *pointer_3);
printf("pointer_1: %s, %p\n", pointer_1, pointer_1);
printf("pointer_2: %s, %p\n", pointer_2, pointer_2);
printf("pointer_3: %s, %p\n", pointer_3, pointer_3);
while(1){}
return 0;
}
将其编译后放到Linux下运行,可以在/proc/{pid}/maps中看到各个变量内存位于的位置:
由此我们可以学习到以下几点:
1、使用pointer_1 = “string_init”;时,pointer_1指向的是一个只读的内存空间,而使用char pointer_2[20] = {0};申请到的是一块可读可写的空间。对于只读空间,如果有赋值的操作(*pointer_1 = 83;),就会导致core dump。
2、pointer_2和pointer_3在初始化的时候已经存在了自己的地址空间,因此如果想使用pointer_2 = pointer_3;的话就会直接编译报错,不能进行地址的。同样,这种指针也不可以使用++操作。我的理解是这些指针是一开始就固化住的,如果想使用++等操作,你需要重新定义一个char *p = pointer_2;