最近在回顾C语言知识点时发现自己对指针的使用有些生疏了,把遇到的问题记录下来,以加深对指针的理解。
首先看下面的示例,实现将字符串反转输出,如“abcdef”, 输出为“fedcba”, 实现起来是不是很简单?
一开始我也这样觉得,下面是我第一次实现的代码:
int main(void)
{
char *src = "Hello, World";
char *dest = NULL;
int len = 0;
len = strlen(src);
dest = (char *)malloc(len+1);
if (dest == NULL) {
printf("dest malloc failed.\n");
return 0;
}
while (len-- != 0) {
*dest++ = src[len];
}
*dest = 0;
printf(“Sting dest: %s\n”, dest);
free(dest);
return 0;
}
看起开没问题,使用gcc -o test test.c也顺利编译通过了,但执行./test时发现竟然报错了,错误如下:
*** Error in `./test_bak': munmap_chunk(): invalid pointer: 0x00000000023f201c ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f931d8317e5]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x1a8)[0x7f931d83e698]
./test_bak[0x40068e]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f931d7da830]
./test_bak[0x400529]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 1325569 /home/lipf/works/C_Project/lesson/lesson_1/test_bak
00600000-00601000 r--p 00000000 08:01 1325569 /home/lipf/works/C_Project/lesson/lesson_1/test_bak
00601000-00602000 rw-p 00001000 08:01 1325569 /home/lipf/works/C_Project/lesson/lesson_1/test_bak
023f2000-02413000 rw-p 00000000 00:00 0 [heap]
7f931d5a4000-7f931d5ba000 r-xp 00000000 08:01 1444647 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f931d5ba000-7f931d7b9000 ---p 00016000 08:01 1444647 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f931d7b9000-7f931d7ba000 rw-p 00015000 08:01 1444647 /lib/x86_64-linux-gnu/libgcc_s.so.1
跟踪代码发现时free(dest)时报了“invalid pointer: 0x00000000023f201c ”的错误,当时有点不太理解为什么会报这样的错误,malloc分配也成功了,没理由会报非法指针的错误。先把free()这里屏蔽掉,看看结果是否如预期的那样,结果发现打印的dest为空,这是为什么呢?
进一步添加printf打印信息,如下:
while (len-- != 0) {
printf("dest point addr: %p\n", dest);
*dest++ = src[len];
printf("src char: %c\n", src[len]);
printf("dest char: %c\n", *dest);
}
将dest的地址以及存放的值打印出来,结果如下:
dest point addr: 0xdb2010
src char: d
dest char:
dest point addr: 0xdb2011
src char: l
dest char:
dest point addr: 0xdb2012
src char: r
dest char:
dest point addr: 0xdb2013
src char: o
dest char:
dest point addr: 0xdb2014
src char: W
dest char:
dest point addr: 0xdb2015
src char:
dest char:
dest point addr: 0xdb2016
src char: ,
dest char:
dest point addr: 0xdb2017
src char: o
dest char:
dest point addr: 0xdb2018
src char: l
dest char:
dest point addr: 0xdb2019
src char: l
dest char:
dest point addr: 0xdb201a
src char: e
dest char:
dest point addr: 0xdb201b
src char: H
dest char:
String dest:
从打印的log可看出dest的值在改变,这里就涉及到了使用malloc()函数分配内存的问题,malloc返回的是分配内存的首地址,所以使用free释放内存时也应该是一开始分配的内存首地址,而示例中执行了*dest++,导致dest的值发生了变化,所以在执行free(dest)时会报错。
那要如何修正错误呢?下面提供了两种方法。
方法一:dest指针使用数组的形式
int i=0;
while (len-- != 0) {
dest[i] = src[len];
i++;
}
dest[len] = '\0';
printf("dest String: %s\n", dest);
free(dest);
方法二:使用指针
dest = (char *)malloc(len + 1);
char *tmp = dest;
while (len-- != 0) {
*tmp++ = src[len];
}
*tmp = '\0';
printf("dest String: %s\n", dest);
free(dest);