设为首页 收藏本站
查看: 630|回复: 1

[c/c++] C++面试八股文:如何在堆上和栈上分配一块内存?

[复制链接]
累计签到:34 天
连续签到:2 天
发表于 2025-1-9 15:13:13 | 显示全部楼层 |阅读模式


某日二师兄参加XXX科技公司的C++工程师开发岗位6面:
面试官: 如何在堆上申请一块内存?
二师兄:常用的方法有malloc,new等。
面试官:两者有什么区别?
二师兄:malloc是向操作系统申请一块内存,这块内存没有经过初始化,通常需要使用memset手动初始化。而new一般伴随三个动作,向操作系统申请一块内存,并执行类型的默认构造函数,然后返回类的指针。
面试官:嗯,那你知道calloc和realloc吗?
二师兄:calloc比malloc多做了一步,就是把申请的内存初始化成0。而realloc则可以改变当前指针所指向的内存块的大小。
面试官:好的。那么你知道这些api/操作符失败会发生什么吗?
二师兄:malloc/calloc/realloc失败会返回NULL,而new失败则会抛出异常。
面试官:有没有让new失败不抛出异常的方法?
二师兄:好像有,但是我不记得了。。。
面试官:没关系。。。我们都知道new和delete成对出现,new[]和delete[]也是成对出现,那么我想问,如果使用new[]创建的对象用delete释放了会发生什么?为什么?
二师兄:额。。。内存泄漏?对,会发生内存泄漏。因为内存没有被释放。
面试官:好的。我们都知道C++中的内存管理是一个比较麻烦的事情,现在有个需求,需要在程序中记录主动申请的内存和主动释放的内存,以确保没有发生内存泄漏。有什么好的方法吗?
二师兄:可以重载new和delete运算符。
面试官:如何重载new和delete运算符?
二师兄:我得查一下资料,这个重载用的很少。。。
面试官:(笑)好吧,最后一个问题,咱们上面一直在讨论堆中的内存的分配和释放,请问一下,如果在栈上分配一块固定的内存?栈中的内存如何释放?
二师兄:额。。。(思考)使用 char[size] ? 应该不需要手动释放。
面试官:好的,回去等通知吧。
对于二师兄的表现,小伙伴们能给打几分呢?我们先看看二师兄在面试中表现不太好的地方:

面试官:有没有让new失败不抛出异常的方法?
在C++中我们可以使用以下方法使得new运算符不抛出异常,
[C++] 纯文本查看 复制代码
int* p = new (std::nothrow) int(42);

if(p == nullptr)
{
    //分配失败
[align=left]}
这个特性需要C++11支持。

再看下一个问题:
如果使用new[]创建的对象用delete释放了会发生什么?
一定会发生内存泄漏吗?答案是,不一定。这取决于类型T。我们先看第一种情况:
[C++] 纯文本查看 复制代码
class Foo
{
public:
    Foo():num_(42){}
private:
    int num_;
};

Foo* pf = new Foo[1024];
delete pf;
当类型T没有管理资源时,delete pf会把整个申请的1024个Foo所占用的内存全部归还给操作系统,此时并没有内存泄漏。再看下一种情况:
[C++] 纯文本查看 复制代码
class Foo
{
public:
    Foo():num_(new int(42)){}
    ~Foo(){delete num_;}
private:
    int* num_;
};

Foo* pf = new Foo[1024];
delete pf;
此时会造成内存泄漏,原因很简单。在执行delete[]时,首先逆序执行每个元素的析构函数,然后再把整块内存归还给操作系统。而delete只会把内存还给操作系统,没有执行析构函数。当类没有资源需要管理时,执行与不执行析构函数都无关紧要,但是当类中需要管理资源时,析构函数的执行就至关重要了。

如何重载new和delete运算符?
[C++] 纯文本查看 复制代码
#include <iostream>
#include <cstdlib>
#include <map>
struct MemoryInfo {
    size_t size; const char* file;
    int line;
};

std::map<void*, MemoryInfo> memoryMap;

void* operator new(size_t size, const char* file, int line) {
    void* ptr = std::malloc(size);
    memoryMap[ptr] = {size, file, line};
    return ptr;
}

void operator delete(void* ptr) noexcept {
    auto it = memoryMap.find(ptr);
    if (it != memoryMap.end()) {
        std::free(ptr);
        memoryMap.erase(it);
    }
}

#define new new(__FILE__, __LINE__)

int main() {
    int* p = new int(42);

    for (const auto& [ptr, info] : memoryMap) {
        std::cout << "Memory allocated at " << ptr << " with size " << info.size
                  << " in file " << info.file << " at line " << info.line << std::endl;
    }
    
    delete p;
    
    for (const auto& [ptr, info] : memoryMap) {
        std::cout << "Memory allocated at " << ptr << " with size " << info.size
                  << " in file " << info.file << " at line " << info.line << std::endl;
    }
    return 0;
}

最后一个问题:
如果在栈上分配一块固定的内存?栈中的内存如何释放?
使用alloca,虽然简单,但是很多人可能都没有接触过:
[C++] 纯文本查看 复制代码
int* p = (int*)alloca(4);
*p = 42;
栈上申请的内存不需要手动释放。注意,如果栈溢出,alloca的行为时未定义的。

好了,今日份面试到这里就结束了,小伙伴们,对于今天二师兄的面试,能打几分呢?



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-1005667-1-1.html 上篇帖子: C++面试八股文:指针占用多少个字节? 下篇帖子: C++面试八股文:static和const的关键字有哪些用法?
累计签到:34 天
连续签到:2 天
 楼主| 发表于 2025-1-9 15:14:13 | 显示全部楼层
<顺便吆喝一句,民族企业大厂,前后端测试捞人,感兴趣的来!→https://jsj.top/f/o38ijj>

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表