const和指针的问题
一个bug引起的
最近北京那边同事碰到了一个问题,找到我时说是已经搞了四五天, 说是软件发布在即十分紧急啥的。 出问题的代码大概是这个样子:
1 |
|
这段代码就是要通过DNS查找主句IP地址,如果成功的话会有一个callback。 问题是一直都无法正确的获得IP地址。
const 和指针的一些说明
一个很流行的面试题就是const int * p 和 int * const p的区别。 其实const int * 和 int const * 是一样的, 就是一个指向const int的指针。 而 int * const p表示一个指向int的const 指针。
那么问题来了,有人会问可以通过指针来修改const 变量的值吗?
1 | int main() { |
上面的代码将没有用const int * 的指针, 而是用int * 的指针来强制改变a的值。 这段代码的结果是什么呢? 其实这个要看编译器。
对于gcc 结果会是
1 | 2 2 |
即const 变量a的值可以被改变。
但如果用g++编译, 结果就是
1 | 1 2 |
其实如果去看汇编的代码,会发现其实a的值还是被改变了,所以 * p的值会是2. 但C++编译器会把a的值直接替换为1, 而不是去a的地址取值, 所以a的值是1.
但如果a是一个全局变量 或是静态变量 ,这段代码运行时会segmentation fault, 因为这时a是在只读的区域的,修改只读区域会使程序出错。
而前面的例子中a是一个局部变量,是在栈中分配的,所以是可以被修改的。
问题的原因
对于开始提到的那个bug, SERVER_NAME其实是一个字符串的指针,并且是在只读区,而我同事封装的这个函数gethostbyname()的参数需要是一个可读写的地址(因为一些底层硬件上的原因)。
而偏偏这个程序所在的平台,虽然不可以通过指针去修改全局const变量 ,但程序不会crash。 所以同事可能没有去考虑这方面的问题。
改成这样就一切正常了。 虽然不同编译器的行为有些不同, 但编程时最好不要通过指针去修改const的变量 。
1 | void main() { |