指针复制与内存泄漏规避:为何const char* q=p修改q不影响p?
关于指针复制与内存泄漏的问题解答
一、为什么复制指针q后,修改q不影响p?
你搞混了指针变量本身和指针指向的内存这两个完全不同的东西:
const char* p是一个指针变量,它存在栈上,里面存的是堆中字符串的起始地址(比如0x1234)。const char* q = p只是把p里存的地址(0x1234)复制给q。q是另一个独立的指针变量,它自己在栈上占另一个位置(比如0x5678),但里面存的地址和p一样,所以一开始两者指向同一块堆内存。- 代码里的
++q是修改q这个变量里的地址值(比如从0x1234变成0x1235),这只会改变q自己的指向,完全不会改动p变量里的内容,所以p始终指向原来的起始地址。 - 而
*q = '_'是修改q当前指向的内存地址里的内容,因为p也指向同一块内存,所以printf(p)会看到修改后的结果——代码注释说“Only q was modified”,意思是只有q的指向在循环中移动了,p全程没变化,但它们共享的内存被修改了。
你之前误以为const char* q是指向指针p,那是指针的指针(写法是char** q = &p)才有的逻辑。另外要注意:原代码里const char*声明的指针,却直接修改*q,这违反了const限定,属于未定义行为,是代码本身的问题。
二、操作指针时,如何复制避免内存泄漏?
指针复制分两种场景,核心是搞清楚要复制的是指针变量还是指针指向的内存:
仅复制指针变量(浅拷贝,如代码里的
q = p):- 这种操作不会分配新内存,只是多了一个指向同一块内存的指针。
- 注意事项:同一块堆内存只能被free一次,由任意一个指向它的指针调用free都可以,但不能重复free。另外,不要提前free后还继续使用指针,也不要丢失指向堆内存的指针(比如把p重新赋值成其他地址,原来的堆地址没保存,就没法free了)。
复制指针指向的内存(深拷贝,让新指针指向独立内存):
- 如果需要新指针和原指针互不干扰,就要用深拷贝。针对字符串可以用
strdup,针对任意内存用malloc+memcpy:char* p = asprintf("name: %s", name); char* q = strdup(p); // 把p指向的字符串复制到新的堆内存,q指向这块新内存 // 此时修改*q不会影响*p,反之亦然 free(p); // 各自释放各自的内存 free(q);
- 如果需要新指针和原指针互不干扰,就要用深拷贝。针对字符串可以用
- 内存泄漏的本质是堆内存分配后未被释放,只要记住:每用
malloc/calloc/realloc/asprintf/strdup这类函数分配的堆内存,都要对应调用一次free,且不要丢失指向该内存的指针。
内容的提问来源于stack exchange,提问作者20MikeMike
相关产品推荐
相关产品推荐

