堆内存的作用域
Scope of Heap Memory
据我所知,堆在本质上应该是全局的,不是吗?因此,我们应该能够在函数中的任何位置访问堆内存。那么为什么下面的代码是segfault(Segmentation Fault)呢?
#include <stdio.h>
using namespace std;
void A(int* x)
{
x = new int[10];
for(int i = 0; i< 10; i++)
{
x[i] = i;
}
}
void B(int *x)
{
printf("%d", x[8]);
}
int main()
{
int* a = NULL;
A(a);
B(a);
return 0;
}
由于指针a
是按值传递的,因此调用方看不到在A()
内所做的更改,从而导致NULL
指针在B()
内被取消引用,因此会发生分段错误。要更正,请通过引用A()
:传递指针
void A(int*& x)
正如其他答案所示,实际上问题是A()
中分配的内存没有传递给B()
。
但值得注意的是,您可以使用免费可用的工具使用静态分析来检测这个问题。
当我在您的示例上运行clang++
3.4版时,它给出:
$ make
clang++ -Wall -Wextra --analyze -c -o go.o go.cpp
go.cpp:16:16: warning: Array access (from variable 'x') results in a null pointer dereference
printf("%d", x[8]);
^~~~
1 warning generated.
在这个特殊的独立示例中,编译器评估路径的额外时间可以忽略不计,这真是太棒了。这可能会在"真实"代码(而不是像这样的合成示例)上增加一些开销。但对于大多数用户来说,这几乎是值得的。
问题:据我所知,堆在本质上应该是全局的,不是吗?
答案:是。
语句:因此,我们应该能够在函数中的任何位置访问堆内存。
响应:是的,只要我们知道堆内存值,我们就可以。
问题:那么为什么下面的代码是segfault(Segmentation Fault)?
答案:在一个函数中分配堆内存并不能保证内存值在其他函数中可见。operator new
返回的地址必须以某种方式提供给其他函数。你可以通过以下几种方式做到这一点:
-
按照Subhajit的建议,将参数类型更改为
int*& a
。 -
让
A
返回分配的内存地址。int* A() { int* x = new int[10]; for(int i = 0; i< 10; i++) { x[i] = i; } return x; }
对于A,A(A)和B(A)调用都是按值。因此,A()或B()内部的任何更改都不会受到调用方的影响。
请致电,
void A(int*& a);
相关文章:
- 未在作用域中声明unordered_map
- 有没有一种方法可以在编译时获得作用域类名
- C++quit()函数中可能存在作用域问题
- 未在此作用域OpenCV3.4中声明cvSaveImage
- 全局作用域中函数指针的赋值
- 在类函数中初始化外部作用域变量
- 我的boost managed_shared_memory在离开作用域时似乎不会从内存空间中取消映射
- 在释放了所有作用域内指针之后仍然可访问内存
- 具有类作用域的动态分配堆栈内存
- 我无法在堆内存和 OOP 作用域之间建立联系
- 内存分配器作用域的设计
- 文字值的作用域是什么,编译器如何为它分配内存
- 在作用域之外新建和删除内存管理
- c++新内存替换和作用域解析
- c++局部作用域减少内存
- std::string如何保持超出作用域的内存而不发生泄漏
- 局部变量在超出作用域时删除另一个变量的内存
- 分配函数作用域成员是否会导致内存泄漏
- 关于从内存中释放链表的析构函数的逻辑和作用域的问题
- 堆内存的作用域