• 请不要在回答技术问题时复制粘贴 AI 生成的内容
kerrspace
V2EX  ›  程序员

C++一个指针,我怎么知道传进来的地址是在堆上还是在栈上?

  •  
  •   kerrspace · Oct 6, 2022 · 4377 views
    This topic created in 1489 days ago, the information mentioned may be changed or developed.

    假设我这个指针在 class 里面,从外面传进来的数据它既有可能是一个定义在栈区的 object ,又有可能是 new 在堆区上的

    譬如我有一个 computer class ,然后 computer::computer(cpu*, gpu*, memory*) 在 int main 里面,我既可以 cpu c; gpu g; meory m; 然后 computer(&c, &g, &m)

    也可以 computer(new cpu, new gpu, new memory)

    那我在 class 里面怎么优雅地判断是哪一种情况?(要不要析构的时候销毁这三个 new ?)

    BTW 。。我知道最简单的方法肯定是你就不要这么写

    22 replies  •  2022-10-08 09:42:55 +08:00
    lmshl
    lmshl
    Oct 6, 2022 via iPhone
    1
    按 c++ move 写不就行了?
    lmshl
    lmshl
    Oct 6, 2022 via iPhone
    2
    不使用 move 的话,比较简单的原则是谁创建谁销毁
    yanqiyu
    yanqiyu
    Oct 6, 2022
    3
    真的写出这种代码的话给调用者带来的迷惑不是一点半点...
    堆栈生长方向不一样,你随便把这个指针和局部变量比大小就行,毕竟是 caller 传给你的
    但是不要这么做,最好要么始终不转移所有权,要么始终转移所有权,要么用智能指针
    HFcbyqP0iVO5KM05
    HFcbyqP0iVO5KM05
    Oct 6, 2022 via iPhone❤️1
    5
    判断一个内存段是否属于 heap ,需要借用 mm_struct 里面的 start_brk(heap 内存段的开始位置) 和 brk(heap 内存段的结束位置)。vma 的开始和结束地址在 mm_struct 的 start_brk 和 brk 之间,则说明地址在 heap 内存中。
    leimao
    leimao
    Oct 6, 2022
    6
    > 那我在 class 里面怎么优雅地判断是哪一种情况?(要不要析构的时候销毁这三个 new ?)
    最好不要这么干,object 不 own 那些 memory ,就别去干 delete 的事。
    heiher
    heiher
    Oct 6, 2022 via Android
    7
    c++不用自动内存管理,就要显式约定 ownership ,不需要判断
    BrettD
    BrettD
    Oct 6, 2022 via iPhone
    8
    你这样写还这样问就说明没有把所有权归属问题想清楚
    leonshaw
    leonshaw
    Oct 6, 2022
    9
    你也知道不要这么写,所有权也是函数 contract 的一部分。并且完全可以分配一块堆内存作为线程的栈(默认情况也是和堆类似分配方式)。
    shawnsh
    shawnsh
    Oct 6, 2022 via Android
    10
    谁创建的指针,谁知道是用的哪个区,让他管回收,你只是使用,你不要管回收。如果要回收,那么就需要知道该指针的类型,是哪个区的。所以你要封装个对象,里面要有一个指针,还要有指针所在的区域,还要有是否调用者可以释放的标记,是不是超级麻烦
    Nitroethane
    Nitroethane
    Oct 6, 2022❤️1
    11
    @gulu #5 写内核模块才能这样搞,用户态进程肯定不行。

    解析 /proc/[pid]/maps 文件,从这个文件中可以知道进程的虚拟地址空间布局,包括 stack 和 heap 的地址范围。
    ColorfulBoar
    ColorfulBoar
    Oct 7, 2022
    12
    正常人的裸指针不带 ownership (当然喜欢指针的没一个正常人就是了)
    另外在内存哪个区域和 storage duration 是两码事,比如如果外面是个 coroutine 那即使已经知道是 automatic storage duration+没有重载 operator new ,也可能被分配在堆上(同时编译器也可能优化成在栈上)
    mingl0280
    mingl0280
    Oct 7, 2022 via Android
    13
    不要删就完了。
    谁分配的谁清理。
    dearmymy
    dearmymy
    Oct 7, 2022
    14
    开始想判断堆跟栈 地址,但想想如果这个整个都 new 在堆里。
    感觉靠谱的,得栈帧一步步回溯?然后判断堆地址区间?
    iceheart
    iceheart
    Oct 7, 2022 via Android
    15
    通过调用栈取到最接近栈顶的地址,定义一个栈上的变量,取到这个变量的地址。在此区间的指针就是栈上的
    littlewing
    littlewing
    Oct 7, 2022
    16
    在堆上也不一定要 delete 啊,说不定创建者自己要 delete 呢,说白了还是 ownership 的问题,建议你用 unique_ptr 或 shared_ptr 。一定要用裸指针的话,遵循谁 new 谁 delete 的原则,除非是在异步回调里
    wtsamuel
    wtsamuel
    Oct 7, 2022
    17
    那应该去问创建这个指针的人
    还得讨论下应不应该修改, 删除这个指针的值
    whi147
    whi147
    Oct 7, 2022 via iPhone
    18
    谁创建谁清理,全部更换智能指针,少用共享智能指针
    calloc
    calloc
    Oct 7, 2022 via iPhone
    19
    去 /proc/self/maps 比对一下
    yolee599
    yolee599
    Oct 7, 2022 via Android❤️1
    20
    谁创建谁清理原则,不要随便 delete 别人传进来的指针
    FrankHB
    FrankHB
    Oct 7, 2022
    21
    你要优雅,就先干掉 computer::computer(cpu*, gpu*, memory*)这种看不出让你怎么干的废物签名。
    基本上除非在写分配器的实现,你一个一般应用的作者,没什么理(资)由(格)在 API 中用指针。
    (写内核之类的东西原则上几乎都得依赖 ABI ,使用的假设比 C++的指针多得多。)
    hu8245
    hu8245
    Oct 8, 2022 via Android
    22
    我实在想不出什么普通场景需要这种骚操作,你操作了,人家释放的时候出问题了,算函数内的操作还是 caller ?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1935 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 64ms · UTC 00:03 · PVG 08:03 · LAX 16:03 · JFK 19:03
    ♥ Do have faith in what you're doing.