指针作为参数传入函数的陷阱
下面以一个例子来引出这种错误:
#include <iostream> using namespace std; #include <stdlib.h> #include <string.h> void func(int *p) { p = (int *)malloc(sizeof(int) * 10); memset(p, 0, sizeof(p)); p[0] = 1; } int main() { int *p = NULL; func(p); cout << p[0] << endl; return 0; }
一个很简单的函数,就是给*p
在函数中分配空间并将p[0]
置成1,最后打印输出p[0]
。但是运行的结果却是segmengt fault
。
我们通过查看这段程序的汇编代码来分析一下出现段错误的原因。
Dump of assembler code for function func(int*): 0x00000000004008cd <+0>: push %rbp 0x00000000004008ce <+1>: mov %rsp,%rbp 0x00000000004008d1 <+4>: sub $0x20,%rsp 0x00000000004008d5 <+8>: mov %rdi,-0x18(%rbp) 0x00000000004008d9 <+12>: mov $0x28,%eax 0x00000000004008de <+17>: mov %rax,%rdi 0x00000000004008e1 <+20>: callq 0x400780 <malloc@plt> 0x00000000004008e6 <+25>: mov %rax,-0x8(%rbp) 0x00000000004008ea <+29>: mov -0x8(%rbp),%rax 0x00000000004008ee <+33>: mov $0x8,%edx 0x00000000004008f3 <+38>: mov $0x0,%esi 0x00000000004008f8 <+43>: mov %rax,%rdi 0x00000000004008fb <+46>: callq 0x400750 <memset@plt> 0x0000000000400900 <+51>: mov -0x8(%rbp),%rax 0x0000000000400904 <+55>: movl $0x1,(%rax) 0x000000000040090a <+61>: leaveq 0x000000000040090b <+62>: retq End of assembler dump.
重点放在
sub $0x20,%rbp mov %rdi,-0x18(%rbp)
这两句汇编代码上。
sub $0x20,%rbp的意思是给栈分配0x20大小的空间。
而mov %rdi,-0x18(%rbp)的意思是把函数的第一个参数的值压入栈中存储。
这说明了什么?说明了函数中的*p其实是一个临时变量,和主函数并不是同一个*p了。给临时变量申请内存并赋值当前不能反映到主函数的*p上,所以主函数的*p还是个空指针,而打印空指针当然就段错误了。
下面介绍两种解决方法:
1.函数返回临时指针的地址:
#include <iostream> using namespace std; #include <stdlib.h> #include <string.h> int* func(int *p) { //此时的p是个临时指针 p = (int *)malloc(sizeof(int) * 10); memset(p, 0, sizeof(p)); p[0] = 1; return p; //返回地址 } int main() { int *p = NULL; p = func(p); cout << p[0] << endl; return 0; }
2.传入指向指针的指针:
#include <iostream> using namespace std; #include <stdlib.h> #include <string.h> //*p存储的是main函数*ptr的地址 void func(int **p) { *p = (int *)malloc(sizeof(int) * 10); memset(*p, 0, sizeof(*p)); *p[0] = 1; } int main() { int *ptr = NULL; func(&ptr); cout << ptr[0] << endl; return 0; }
如果传的是已分配了内存空间的变量,则不需要指针的指针处理。如下:
void func(int *p) { p[0] = 99; } int main() { int *p = NULL; p = (int *)malloc(sizeof(int) * 10); func(p); cout << p[0] << endl; return 0; }
转 https://blog.csdn.net/Move_now/article/details/71944689