C++向函数传递类实例引发的问题及原理咨询
C++值传递引发的Buffer内存异常问题解析
先看你的Buffer类实现:
#pragma once #include <stdint.h> #include <stdlib.h> #include <string.h> class Buffer { public: Buffer(uint16_t bytes) { ptr = malloc(size = bytes); } ~Buffer() { free(ptr); } inline char* str() { return (char*)ptr; } inline int length() { return strlen(str()); } void* ptr; uint16_t size; };
针对你的问题逐一解答:
非引用参数的函数签名含义
writeSomething(Buffer buffer)这种签名表示:函数接收一个Buffer类型的参数副本,属于C++里的值传递方式。函数内部对这个buffer参数的修改不会影响到外部的原对象。
传递的是什么
当你调用writeSomething(text)时,编译器会自动创建一个text对象的浅拷贝副本——因为你的Buffer类没有自定义拷贝构造函数,编译器会生成默认的拷贝构造函数,把原对象的ptr和size成员直接复制给副本对象。这就导致副本的ptr和原对象text的ptr指向同一块堆内存。
为何析构函数会在此处触发
当writeSomething函数执行完毕时,函数内的局部变量(也就是那个Buffer副本buffer)会被销毁,此时会自动调用Buffer的析构函数~Buffer(),而析构函数里会调用free(ptr)释放这块共享的内存。
此时原对象text的ptr还指向已经被释放的内存,后续执行doSomethingElse(text.ptr)时,就会访问已经被释放的堆内存,触发内存异常。
而改成writeSomething(Buffer& buffer)(引用参数)后,函数接收的是原对象text的引用,不会创建副本,函数结束后也不会有局部对象销毁,自然不会触发析构函数释放内存,原对象的ptr依然有效,问题就解决了。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

