2010-08-10 37 views
3

如果* get_ii()返回堆内存,而不是堆栈内存,这个问题是否会被消除?指针电阻

01 int *get_ii() 
02 { 
03 int ii;  // Local stack variable 
04 ii = 2; 
05 return ⅈ 
06 } 
07 main() 
08 { 
09 int *ii; 
10 ii = get_ii(); // After this call the stack is given up by the routine 
11     // get_ii() and its values are no longer safe. 
12  
13 ... Do stuff 
14 .. ii may be corrupt by this point. 
15 } 

来源 - http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html

感谢

+0

与返回引用相同的问题,自动对象的生命周期以范围结束。在大多数情况下,只需返回一个值。(Do * not * pre-optimize and say“哦,但是我会复制一个大对象,所以我不应该那样做!我会通过引用作为参数或返回一个指向动态分配值的指针“但是不要。) – GManNickG 2010-08-10 17:51:17

回答

7

是的。从堆分配将在这里工作。确保你再次释放它,否则你会泄漏内存。

智能指针通常会帮助您处理这种“不要忘记”的逻辑。

+1

智能指针+1。不使用RAII这种事情可能是一个坏主意。 – Brian 2010-08-10 17:48:22

+1

返回一个值几乎肯定会更好。即使对象足够大,复制速度会比分配速度慢,但大多数编译器都会无视这一副本。 – 2010-08-10 18:48:40

+0

所以问题是,一旦它从get_ii函数中释放,返回的ii地址就意味着什么? – 2010-08-10 19:14:56

2

,因为当你在主访问II将发生在你的代码的问题,get_ii()返回之后,你的变量通过II访问时已经被破坏。

如果返回分配了从get_ii堆内存,那么内存可以被访问,直到它被显式销毁

3

右键 - 从堆(使用malloc分配的,例如)内存将持续外get_ii()的范围。只要确保释放它。你也可以分配ii作为static int ii,在这种情况下,它的指针也会存在于get_ii()之外。

+2

虽然,一个警告是将其声明为”静态“,然后将其设置为所有调用该函数的副本。这是一个设计决定,应该通过预先考虑和理解来做出,并且绝对不是在多线程程序中应该做的。 – Omnifarious 2010-08-10 17:55:48

+0

它甚至不需要线程成为一个问题。如果程序中的一个点获得指针并保持在其上,则另一个点可以做同样的事情,并且在一个地方对值的更改会影响另一个点。 – KeithB 2010-08-10 19:37:13

3

您基本上返回不再存在的变量的地址(ii在函数get_ii()开始执行时创建,并且仅在函数退出之前存在)。对main()int *ii指向的内存的任何访问都会导致未定义的行为。

另一方面,堆内存是在您明确请求它时分配的,并且在您明确请求它之前不会释放它。所以如果你在一个函数内部分配一个内存块,把指针返回给那个内存块是非常好的。只需确保在不再需要时释放内存块的人员负责记录谁是谁!

0

如果你正在编写C风格的代码,那么要做的事情就是传入一个指向对象的指针并通过该指针修改对象。这样get_ii函数不用担心对象来自哪里。调用函数会照顾它。

如果你正在编写C++风格,那么你应该返回值或返回一个智能指针或采取引用并通过该引用修改对象。或者你可以使用C风格并传递一个指针。一些C++作者更喜欢指针传递,因为它明确指出对象正在被修改,而引用传递不明确。

现在,如果对象在这个例子中很小,那么您应该总是按值传递并返回它。它比使用指针更快,更便宜,并且使编码更简单。

+0

即使返回的对象很大,返回值优化可能允许编译器在它返回的位置构造它,以消除任何复制。 – jcoder 2010-08-10 18:05:14

+0

如果你正在返回一个结构体,通常的ABI实际上将一个指向一个结构体的指针作为第一个参数来填充,使它等价于pass-a-pointer版本。由于潜在的异常(也可能是线程),会有一些差异,但是如果您分配给本地,它应该做正确的事情(并且可能会优化得更好)。 – 2010-08-10 18:58:37

2

甚至更​​恶毒:

std::string& makeString() //returns a reference 
{ std::string str = "Dustin"; return str; } 

main(){ 
std::string s = makeString(); 
//s is a dangling reference! makeString returns a reference to str, 
//but str is on the stack and goes out of scope, so we're keeping a reference to nothing 
} 

STR(内部makeString)是在堆栈上和makeString返回时被破坏。 通过返回by-value而不是by-reference来解决此错误,这会在str超出范围之前对str进行复制。

+0

我认为堆栈变量被破坏?其次,这个错误如何解决? – 2010-08-10 19:27:48

+0

更新了我的答案 – 2010-08-10 19:53:34