面试官问:malloc(0)时程序会返回什么?

今天跟大家找了篇文章,主要是一个面试中的有趣问题,其实有些问题在开发中没有遇到过会很难回答出来,如果在面试过程中回答正确,皆大欢喜,拿到offer的概率更大;回答不出来也不要信口开河,面试官主要看的是你对待问题的态度~

正文:

故事要从前两天交流群中一位同学提到的这个问题开始

4f8355d7d7be84209834dcdeb1e657b4.png

这个问题看起来十分刁钻,不过稍有常识的人都知道,制定 C 标准的那帮语言律师也不是吃白饭的,对这种奇奇怪怪的问题一定会有定义。翻阅C17 标准 草案 N2176,在 7.22.3 节里,有如下说法:

The order and contiguity of storage allocated by successive calls to the aligned_alloc, calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned to indicate an error, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.

在这里,标准委员会明确规定了:当 malloc 接到的参数为 0 时,其行为是由实现定义的(implementation-defined)。

由实现定义的行为这个词就提醒我们,在实际编程时如果要考虑到程序在多个运行环境下进行运行时,不能对 malloc 返回的数值进行任何假设。

换言之,没事儿不要吃饱了撑的在实际编程中写下 malloc(0) 这种天怒人怨的代码。

但是,这个无意义的问题吸引了我的兴趣。因此我开始查阅 glibc 的源代码,依此了解在 glibc 下,mallloc(0) 的行为。在 glibc2.27/malloc/malloc.c 中,有如下注释:

/*malloc(size_t n)Returns a pointer to a newly allocated chunk of at least n bytes, or nullif no space is available. Additionally, on failure, errno isset to ENOMEM on ANSI C systems.If n is zero, malloc returns a minumum-sized chunk. (The minimumsize is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bitsystems.)  On most systems, size_t is an unsigned type, so callswith negative arguments are interpreted as requests for huge amountsof space, which will often fail. The maximum supported value of ndiffers across systems, but is in all cases less than the maximumrepresentable value of a size_t.
*/

注释已经说的很清楚了,当我们执行 malloc(0) 时,我们实际会拿到一个指向一小块内存的指针,这个指针指向的(分配给我们的)内存的大小是由机器决定的

细读代码,可以发现,将读入的内存大小进行转换是由宏 checked_request2size 实现的。

相关的宏定义如下:

/* pad request bytes into a usable size -- internal version */
#define request2size(req)                                         \(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE)  ?             \MINSIZE :                                                      \((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)/* Same, except also perform an argument and result check.  First, we checkthat the padding done by request2size didn't result in an integeroverflow.  Then we check (using REQUEST_OUT_OF_RANGE) that the resultingsize isn't so large that a later alignment would lead to another integeroverflow.  */#define checked_request2size(req, sz) \
({        \(sz) = request2size (req);     \if (((sz) < (req))      \|| REQUEST_OUT_OF_RANGE (sz)) \{        \__set_errno (ENOMEM);     \return 0;       \}        \
})

也就是说,我们能申请到的数值最小为 MINSIZE ,这个 MINSIZE 的相关定义如下:

/* The smallest possible chunk */
#define MIN_CHUNK_SIZE        (offsetof(struct malloc_chunk, fd_nextsize))
/* The smallest size we can malloc is an aligned minimal chunk */
#define MINSIZE  \(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))/* The corresponding bit mask value.  */
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
/* MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.  Itmust be a power of two at least 2 * SIZE_SZ, even on machines forwhich smaller alignments would suffice. It may be defined as largerthan this though. Note however that code and data structures areoptimized for the case of 8-byte alignment.  */
#define MALLOC_ALIGNMENT (2 * SIZE_SZ < __alignof__ (long double) \? __alignof__ (long double) : 2 * SIZE_SZ)#ifndef INTERNAL_SIZE_T
# define INTERNAL_SIZE_T size_t
#endif/* The corresponding word size.  */
#define SIZE_SZ (sizeof (INTERNAL_SIZE_T))/*This struct declaration is misleading (but accurate and necessary).It declares a "view" into memory allowing access to necessaryfields at known offsets from a given base. See explanation below.
*/struct malloc_chunk {INTERNAL_SIZE_T      mchunk_prev_size;  /* Size of previous chunk (if free).  */INTERNAL_SIZE_T      mchunk_size;       /* Size in bytes, including overhead. */struct malloc_chunk* fd;         /* double links -- used only if free. */struct malloc_chunk* bk;/* Only used for large blocks: pointer to next larger size.  */struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */struct malloc_chunk* bk_nextsize;
};// GCC 提供
/* Offset of member MEMBER in a struct of type TYPE. */
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)

至此,我们就可以根据这些计算出使用 glibc 在我们的电脑上运行时 malloc 出的最小空间的大小了。计算完后,还可以根据 malloc_usable_size 判断自己的计算是否正确,样例代码如下:

#include <stdio.h>
#include <malloc.h>
int main(void) {char *p = malloc(0);printf("Address: 0x%x.\nLength: %ld.\n",p,malloc_usable_size(p));return 0;
}

该样例在我电脑内输出的结果为 24。

因此,我们知道了,在 glibc 下,执行 malloc 会得到一个指向分配给我们的大小为 24 字节的内存空间的指针。

但这只是在 glibc 下的结果,在其他 C 标准库实现内,可能你会得到一个空指针。因为标准中提到了,对于 malloc(0) 这种故意挑事的代码,实现时可以返回一个空指针作为回礼。

素材源于:文章来源:https://zhuanlan.zhihu.com/p/40490357

直接来源:嵌入式与linux那些事

版权归原作者所有。仅供技术的传播和学习讨论,如涉及作品版权问题,请联系我进行删除。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/465270.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2018 Machine Learning

2018/8/13 线性模型(西瓜书P53~P73)Optimizerhttps://blog.csdn.net/u012151283/article/details/781549172018/8/15 SVM(西瓜书)2018/8/16 面试题 https://www.cnblogs.com/zuochongyan/p/5407053.html熵、联合熵、条件熵、交叉熵与相对熵 &#xff1f;&#xff1f;归一化方法…

考研失败了,怎么办?

有读者提到这个问题&#xff0c;顺带回答下。我没有考研过&#xff0c;但是身边有很多研究生和博士&#xff0c;额&#xff0c;还有很多海外留学的博士。前天我们有外部厂商来公司讨论合作&#xff0c;领导让我跟着一起介绍项目&#xff0c;对方的人问了一句&#xff1a;“你们…

10月28号日志

匆匆忙忙而来&#xff0c;怀着梦想、怀着希望来到苏州这个地方。想用自己在校学的知识来改变自己的命运&#xff0c;我空空而来想满载而归。在这一段的时间里&#xff0c;我深深感受到了同学情深&#xff0c;深似海。老师恩重重如山。在长生果科技有限公司工作已将近两个月了的…

在php中怎么用js跳转页面跳转,在php中怎么用redirect实现页面跳转?

1、thinkPHP 的Action类的redirect方法可以实现页面的重定向功能&#xff0c;redirect 重定向的通用语法为&#xff1a;edirect(url,paramsarray(),delay0,msg) // 跳转到 edit 操作 $this->redirect(edit)。2、// 跳转到 UserAction下的edit 操作 this->redirect(User/…

[BZOJ 4025] 二分图

题目传送-BZOJ4025 题意&#xff1a; 有一张\(n\)个节点的无向图,其中边\(i\)在\(s_i\)出现,\(e_i\)结束,并连接着节点\(x,y\). 并保证\(s_i < e_i \le T\),要求对于每个时间\(t\le T\)输出此时的图是否是二分图。\(n\le100000,m\le200000,T\le100000\) 题解&#xff1a; 这…

晒一波工程师的工位,你喜欢哪种?

程序员的圈子啊那是十分神秘&#xff0c;又令人着迷的。每天的工作就是对着电脑&#xff0c;那他们的工作是如何的呢&#xff1f;我们来品一品&#xff08;PS&#xff1a;后面奉上各位大佬的桌面&#xff0c;别走开哦&#xff09;↓↓↓最最常见的普通版&#xff1a;升级版&…

传360以原彩虹QQ研发团队为班底拟强推IM

据知情人士透露&#xff0c;奇虎360开发即时通讯工具IM软件已成定局&#xff0c;正式推出只是时间问题。同时&#xff0c;该知情人还透露&#xff0c;目前负责360公司即时通讯软件项 目的核心班底正是51.com原“彩虹QQ”&#xff08;51.com对外官方产品名称为“彩虹显IP辅助软件…

linux无法安装php-fpm,Linux下的php-fpm相关问题解决

今天搭建LNMP环境时,在安装PHP编译的时候出现了问题,首先在解压安装包后配置检测环境./configure --prefix/usr/local/php \--with-gd \--enable-gd-native-ttf \--enable-mysqlnd \--with-mysqlmysqlnd \--with-pdo-mysqlmysqlnd \--with-openssl \--enable-mbstring \--enabl…

recovery.conf 用于 stream replication

recovery.conf 是 postgresql slave 数据库的重要文件&#xff0c;示例文件为. $ ls -l $PGHOME/share/recovery.conf.sample可以编辑 $PGDATA/recovery.conf 异步stream recovery_target_timeline latest standby_mode on primary_conninfo host192.168.56.201 port5432 us…

彻底搞懂系统调用

在应用程序开发过程中经常会进行IO设备的操作&#xff0c;比如磁盘的读写&#xff0c;网卡的读写&#xff0c;键盘&#xff0c;鼠标的读入等&#xff0c;大多数应用开发人员使用高级语言进行开发&#xff0c;例如C&#xff0c;C&#xff0c;java&#xff0c;python等&#xff0…

getimg()在java中,java – 使用getClass()加载资源getResource()

我正在尝试加载一个图像作为我的应用程序中的一个图标。根据这个tutorial的适当方法是&#xff1a;protected ImageIcon createImageIcon(String path, String description){java.net.URL imgURL getClass().getResource(path);if (imgURL ! null) {return new ImageIcon(imgU…

Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录

0、目录 整体架构目录&#xff1a;ASP.NET Core分布式项目实战-目录 k8s架构目录&#xff1a;Kubernetes(k8s)集群部署&#xff08;k8s企业级Docker容器集群管理&#xff09;系列目录 一、感谢 在此感谢.net core社区的帮助。感谢。 二、系列部署目录 0、部署环境规划 1、自签T…

每天都用手机,你对麦克风了解吗?

简 介&#xff1a; 通过对于实际驻极体MIC进行拆解&#xff0c;看到其中的结构&#xff0c;对比起工作原理&#xff0c;实在令人难以想象它的工作机制是可行的&#xff0c;尽管现在它已经广泛应用在周围很多电子设备中。关键词&#xff1a; 驻极体&#xff0c;MIC01 驻极体话筒…

网络运维管理的质变

未来网络运维趋势 未来的网络发展趋势可以用三个多样化来概括&#xff0c;一是网络设备的多样化&#xff0c;二是网络组网方式的多样化&#xff0c;三是网络应用的多样化&#xff1b;再加上网络发展与信息化建设的紧密结合&#xff0c;这使得未来的网络运维工作面临着新的…

Java @responsebody,springMVC 使用注解@ResponseBody 不能返回JSON数据

控制器中代码RequestMapping(value "/listArea",method RequestMethod.GET)ResponseBodyprivate Map listArea(){Map modelMap new HashMap<>();List list areaService.getAreaList();modelMap.put("rows", list);modelMap.put("total"…

好了,我不想回深圳了~

国庆节算长假&#xff0c;一共七天&#xff0c;高速免费。如果一个人&#xff0c;待在家里睡上七天&#xff0c;可能我在第二天就会特别无聊&#xff0c;想找事情做&#xff0c;因为国庆离开深圳的人很多&#xff0c;我曾经有一次放假去球场打球&#xff0c;结果很失落&#xf…

开源微信管家平台——JeeWx 捷微4.0 微服务版本发布,全新架构,全新UI,提供强大的图文编辑器...

JeeWx捷微4.0 微服务版本发布^_^ 换代产品&#xff08;全新架构&#xff0c;全新UI&#xff0c;提供强大的图文编辑器&#xff09; JEEWX 从4.0版本开始&#xff0c;技术架构全新换代&#xff0c;采用微服务架构&#xff0c;插件式开发&#xff0c;每个业务模块都是独立的JAR…

手把手教用XNA开发winphone7游戏(三)

XNA Game Studio 游戏循环 在这部分中您将重点两剩余部分的游戏 — — 重写Update 和 Draw 功能。有些大大可能看过相关微软的训练包&#xff0c;我这里主要是帮一些初学者。希望各位大大包含&#xff0c;毕竟文章发出来还是有工作量的。大家觉得有用就好&#xff0c;要是没有耽…

我的代码很好,不需要写注释

作者 | Sheetal 译者 | 弯月 责编 | 王晓曼 有时候&#xff0c;我们会写一些非常有创意的注释&#xff0c;而有些注释确实让人不得不佩服 程序员的想象力。看到下面这些注释&#xff0c;相信每个人都会捧腹大笑。【1】#想了解递归&#xff0c;请参见文件末尾 . .&#xff08;代…

陈潇冰php,webpack4.x入门到进阶

课程详情(本课程所涉及内容)1. webpack是什么?webpack的作用2. webpack的整体构成3. webpack-cli、package.json4. 开发环境(development)和生产环境(production)&#xff0c;npm安装包的方式&#xff0c;-D、-S5. 跑一跑webpack6. webpack.config.js配置总览7. 入口配置形式&…