0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

面試題:malloc(0)會(huì)發(fā)生什么?

STM32嵌入式開(kāi)發(fā) ? 來(lái)源:STM32嵌入式開(kāi)發(fā) ? 2023-10-31 16:27 ? 次閱讀

故事要從前兩天交流群中一位同學(xué)提到的這個(gè)問(wèn)題開(kāi)始:

e80411b4-77c2-11ee-939d-92fbcf53809c.png

這個(gè)問(wèn)題看起來(lái)十分刁鉆,不過(guò)稍有常識(shí)的人都知道,制定 C 標(biāo)準(zhǔn)的那幫語(yǔ)言律師也不是吃白飯的,對(duì)這種奇奇怪怪的問(wèn)題一定會(huì)有定義。翻閱C17 標(biāo)準(zhǔn) 草案 N2176,在 7.22.3 節(jié)里,有如下說(shuō)法:

The order and contiguity of storage allocated by successivecalls 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.在這里,標(biāo)準(zhǔn)委員會(huì)明確規(guī)定了:當(dāng) malloc 接到的參數(shù)為 0 時(shí),其行為是由實(shí)現(xiàn)定義的(implementation-defined)。由實(shí)現(xiàn)定義的行為這個(gè)詞就提醒我們,在實(shí)際編程時(shí)如果要考慮到程序在多個(gè)運(yùn)行環(huán)境下進(jìn)行運(yùn)行時(shí),不能對(duì) malloc 返回的數(shù)值進(jìn)行任何假設(shè)。換言之,沒(méi)事兒不要吃飽了撐的在實(shí)際編程中寫(xiě)下 malloc(0) 這種天怒人怨的代碼。但是,這個(gè)無(wú)意義的問(wèn)題吸引了我的興趣。因此我開(kāi)始查閱 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 null
  if no space is available. Additionally, on failure, errno is
  set to ENOMEM on ANSI C systems.


  If n is zero, malloc returns a minumum-sized chunk. (The minimum
  size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit
  systems.)  On most systems, size_t is an unsigned type, so calls
  with negative arguments are interpreted as requests for huge amounts
  of space, which will often fail. The maximum supported value of n
  differs across systems, but is in all cases less than the maximum
  representable value of a size_t.
*/

		注釋已經(jīng)說(shuō)的很清楚了,當(dāng)我們執(zhí)行 malloc(0) 時(shí),我們實(shí)際會(huì)拿到一個(gè)指向一小塊內(nèi)存的指針,這個(gè)指針指向的(分配給我們的)內(nèi)存的大小是由機(jī)器決定的。

細(xì)讀代碼,可以發(fā)現(xiàn),將讀入的內(nèi)存大小進(jìn)行轉(zhuǎn)換是由宏 checked_request2size 實(shí)現(xiàn)的。

相關(guān)的宏定義如下:
/* 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 check
   that the padding done by request2size didn't result in an integer
   overflow.  Then we check (using REQUEST_OUT_OF_RANGE) that the resulting
   size isn't so large that a later alignment would lead to another integer
   overflow.  */


#define checked_request2size(req, sz) 
({        
  (sz) = request2size (req);     
  if (((sz) < (req))      
      || REQUEST_OUT_OF_RANGE (sz)) 
    {        
      __set_errno (ENOMEM);     
      return 0;       
    }        
})
也就是說(shuō),我們能申請(qǐng)到的數(shù)值最小為 MINSIZE ,這個(gè) MINSIZE 的相關(guān)定義如下:

		
/* 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.  It
   must be a power of two at least 2 * SIZE_SZ, even on machines for
   which smaller alignments would suffice. It may be defined as larger
   than this though. Note however that code and data structures are
   optimized 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 necessary
  fields 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)



至此,我們就可以根據(jù)這些計(jì)算出使用 glibc 在我們的電腦上運(yùn)行時(shí) malloc 出的最小空間的大小了。計(jì)算完后,還可以根據(jù) malloc_usable_size 判斷自己的計(jì)算是否正確,樣例代碼如下:
#include 
#include 
int main(void) {
    char *p = malloc(0);
    printf("Address: 0x%x.
Length: %ld.
",p,malloc_usable_size(p));
    return 0;
}

該樣例在我電腦內(nèi)輸出的結(jié)果為 24。

因此,我們知道了,在 glibc 下,執(zhí)行 malloc 會(huì)得到一個(gè)指向分配給我們的大小為 24 字節(jié)的內(nèi)存空間的指針。

但這只是在 glibc 下的結(jié)果,在其他 C 標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)內(nèi),可能你會(huì)得到一個(gè)空指針。因?yàn)闃?biāo)準(zhǔn)中提到了,對(duì)于 malloc(0) 這種故意挑事的代碼,實(shí)現(xiàn)時(shí)可以返回一個(gè)空指針作為回禮。


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 程序
    +關(guān)注

    關(guān)注

    117

    文章

    3794

    瀏覽量

    81266
  • 源代碼
    +關(guān)注

    關(guān)注

    96

    文章

    2946

    瀏覽量

    66842
  • Glibc
    +關(guān)注

    關(guān)注

    0

    文章

    9

    瀏覽量

    7519
  • malloc
    +關(guān)注

    關(guān)注

    0

    文章

    53

    瀏覽量

    75

原文標(biāo)題:面試題:malloc(0)會(huì)發(fā)生什么?

文章出處:【微信號(hào):c-stm32,微信公眾號(hào):STM32嵌入式開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    常見(jiàn)的嵌入式C語(yǔ)言面試題

    數(shù)組是最基本的數(shù)據(jù)結(jié)構(gòu),關(guān)于數(shù)組的面試題也屢見(jiàn)不鮮,本文羅列了一些常見(jiàn)的面試題,僅供參考。目前有以下18道題目。
    發(fā)表于 07-18 10:46 ?833次閱讀

    java基礎(chǔ)練習(xí)、面試題

    java基礎(chǔ)練習(xí)、面試題整理了java私塾教材的課后作業(yè),基礎(chǔ)部分,面試中也常常遇到的基礎(chǔ)問(wèn)題,趕緊下載了。下載: [hide][/hide]
    發(fā)表于 07-16 14:02

    java經(jīng)典面試題深度解析

    免費(fèi)視頻教程:java經(jīng)典面試題深度解析對(duì)于很多初學(xué)者來(lái)說(shuō),學(xué)好java在后期面試的階段都沒(méi)什么經(jīng)驗(yàn),為了讓大家更好的了解面試相關(guān)知識(shí),今天在這里給大家分享了一個(gè)java經(jīng)典面試題深度
    發(fā)表于 06-20 15:16

    c語(yǔ)言面試題,c++面試題下載

    c語(yǔ)言面試題,c++面試題1. static有什么用途?(請(qǐng)至少說(shuō)明兩種) 1) 限制變量的作用域 2) 設(shè)置變量的存儲(chǔ)域 2. 引用與指針有什么區(qū)別?  1) 引用必須被初
    發(fā)表于 10-22 11:19 ?5次下載

    c語(yǔ)言面試題

    c語(yǔ)言面試題集(單片機(jī))C language problem(20151125084232)
    發(fā)表于 12-18 14:05 ?9次下載

    c語(yǔ)言面試題

    c語(yǔ)言面試題
    發(fā)表于 11-05 16:48 ?0次下載

    C語(yǔ)言經(jīng)典面試題

    面試題
    發(fā)表于 12-20 22:41 ?0次下載

    C語(yǔ)言經(jīng)典面試題

    C語(yǔ)言 經(jīng)典面試題
    發(fā)表于 01-05 11:27 ?0次下載

    經(jīng)典硬件面試題精選及解答

    經(jīng)典硬件面試題精選及解答
    發(fā)表于 11-29 18:02 ?0次下載

    Java的經(jīng)典面試題和答案詳細(xì)說(shuō)明

    發(fā)現(xiàn)網(wǎng)上很多Java面試題都沒(méi)有答案,所以花了很長(zhǎng)時(shí)間搜集整理出來(lái)了這套Java面試題大全,希望對(duì)大家有幫助哈~ 博主已將以下這些面試題整理成了一個(gè)Java面試手冊(cè),題型非常全面附帶答
    發(fā)表于 09-07 08:00 ?0次下載
    Java的經(jīng)典<b class='flag-5'>面試題</b>和答案詳細(xì)說(shuō)明

    常見(jiàn)的MySQL高頻面試題

    在各類技術(shù)崗位面試中,似乎 MySQL 相關(guān)問(wèn)題經(jīng)常被問(wèn)到。無(wú)論你面試開(kāi)發(fā)崗位或運(yùn)維崗位,總會(huì)問(wèn)幾道數(shù)據(jù)庫(kù)問(wèn)題。經(jīng)常有小伙伴私信我,詢問(wèn)如何應(yīng)對(duì) MySQL 面試題。其實(shí)很多面試題都是
    的頭像 發(fā)表于 02-08 16:05 ?2429次閱讀

    操作系統(tǒng)的四十多道題面試題

    ? 我之前匯總了一下關(guān)于操作系統(tǒng)的面試題,最近又重新翻閱了一下發(fā)現(xiàn)不是很全,現(xiàn)在也到了面試季了,所以我又花了一周的時(shí)間修訂整理了一下這份面試題,這份面試題可以吊打市面上所有的操作系統(tǒng)
    的頭像 發(fā)表于 03-10 10:17 ?3284次閱讀
    操作系統(tǒng)的四十多道題<b class='flag-5'>面試題</b>

    142道linux面試題,值得收藏

    142道linux面試題,值得收藏
    發(fā)表于 06-16 14:42 ?4次下載

    關(guān)于數(shù)組常見(jiàn)的面試題

    數(shù)組是最基本的數(shù)據(jù)結(jié)構(gòu),關(guān)于數(shù)組的面試題也屢見(jiàn)不鮮,本文羅列了一些常見(jiàn)的面試題,僅供參考。目前有以下18道題目。
    的頭像 發(fā)表于 08-17 09:25 ?1677次閱讀

    硬件工程師經(jīng)典面試題詳解

    硬件工程師經(jīng)典面試題詳解
    的頭像 發(fā)表于 11-20 15:08 ?1496次閱讀
    硬件工程師經(jīng)典<b class='flag-5'>面試題</b>詳解