我正在调查内存泄漏,从我看到的,问题看起来像这样:
int main(){
char *cp = 0;
func(cp);
//code
delete[] cp;
}
void func(char *cp){
cp = new char[100];
}
在//代码注释中,我希望cp指向已分配的内存,但它仍然是一个空指针,这意味着我永远不会删除内存。我在做什么呢?
答案 0 :(得分:18)
您正在为cp
分配已分配内存的值。但是,这是堆栈中的变量:main cp
的副本! cp
是您所在职能的本地。
你想要的是一个参考:
void func(char *& cp)
这将别名cp
作为传入的参数。
答案 1 :(得分:12)
void func(char *cp){
cp = new char[100];
}
在这个函数中,char * cp是一个“指针由 copy 传递”,这意味着它们指向相同的内存地址,但它们不是<强>相同指针。当您更改内部指针,使其指向其他位置时,已传递的原始指针将始终指向0。
答案 2 :(得分:6)
参数cp是函数的局部变量 - 更改它不会改变函数外的任何内容。编写函数的更好方法是:
char * func(){
return new char[100];
}
不要直接处理你的问题,但你应该使用std :: string和std :: vector而不是动态分配的数组。
答案 3 :(得分:1)
您传递的是cbuf
,而不是cp
。
答案 4 :(得分:1)
该功能仅更改cp
的COPY。改为使用引用。
答案 5 :(得分:1)
尽管引用在提供直观抽象方面非常出色,但通过C ++ 11 rvalue引用进一步增强以允许函数链(以及其他深奥编码),可以证明它们提供了任何安全性(即why is a reference considered safer than a pointer) 有些情况下,最好使用指向指针函数参数的指针来解决上述问题。 特别是当需要在ansi c和c ++中维护类似的代码库时。
#include <iostream>
using namespace std;
void func(char ** cp) {
*cp = new char[100];
//do something useful
(*cp)[0] = 'A';
}
void func(char *& cp) {
cp = new char[100];
//do something useful
cp[0] = 'B';
}
int main(int argc, char** argv) {
char * cp;
//pointer to pointer
func(&cp);
cout << "Index 0 : " << cp[0] << '\n' << flush;
delete[] cp; //remember to delete!!
//pointer to ref
func(cp);
cout << "Index 0: " << cp[0] << '\n' << flush;
delete[] cp;
return 0;
}
当然,超出安置功能范围的内存资源的处理违反了RAII。
答案 6 :(得分:0)
正如GMan和Neil所说,为了工作,你必须将func改为:
char* func();
或void func(char*& p);
这将解决您当前的问题。
然而,存在维护问题。在任何一种情况下,func都会返回一个指针。 func的用户不清楚的是返回的指针必须被删除。因此,除非100%必要,否则通常避免使用此构造。更确切地说:
因此,对于C ++代码,我建议:
class CBuf
{
public
CBuf()
{
iBuf = new char[100];
}
~CBuf
{
delete[] iBuf;
}
char* func()
{
//do stuff;
return iBuf;
}
private:
char* iBuf;
};
int main()
{
CBuf cb;
char* mychar = cb.func();
//do stuff with character array
//destructor gets called here because cb goes out of scope
}
但是,特别是在C编程中,使用某种排序函数创建数组可能是100%必需的。因此,在C编程中,您可以使用CreateCBuf
和DestroyCBuf
函数替换析构函数。通过这种方式,库的用户将知道返回的缓冲区需要被销毁。