nullポインターを逆参照すると、未定義の動作が発生します

サイレントNULL(ヌルポインターを逆参照すると、未定義の動作が発生します)
誤って、PがNULLポインターである場合、C / C ++で式&P-> m_fooを使用することが許可されているかどうかについて、大きな議論が生じました。 プログラマーは2つのキャンプに分かれました。 そのように書くことはできないと自信を持って主張する人もいれば、できると自信を持って主張する人もいます。 さまざまな議論や参考文献が引用されました。 そして、私はこの問題を最終的に明確にする必要があることに気付きました。 これを行うために、私はMicrosoft MVPの専門家と、プライベートメーリングリストを介して通信するVisual C ++開発者に頼りました。 彼らはこの記事の準備を手伝ってくれたので、みんなに紹介します。 せっかちな人のために:このコードは正しくありません。

ディスカッション履歴を思い出させてください


すべては、PVS-Studioアナライザーを使用したLinuxカーネルのチェックに関する記事から始まりました。 しかし、カーネルチェック自体はそれとは何の関係もありません。 実際のところ、記事ではLinuxコードから次のスニペットを引用しました。
static int podhd_try_init(struct usb_interface *interface,
        struct usb_line6_podhd *podhd)
{
  int err;
  struct usb_line6 *line6 = &podhd->line6;

  if ((interface == NULL) || (podhd == NULL))
    return -ENODEV;
  ....
}

, , .

. , offsetof, :
#define offsetof(st, m) ((size_t)(&((st *)0)->m))

, . , , .

, . : " ".

, . . .

, , . , . .


'&podhd->line6' C , 'podhd' — .

'&' C99 ( 6.5.3.2 « »):

& , [] *, lvalue-, , .

'podhd->line6' , [] *. lvalue-. , 'podhd' , , 6.3.2.3 «» :

, , , .

«lvalue- , » ( C99, 6.3.2.1 «Lvalue-, »):

lvalue — , void; lvalue- , .

:

-> , lvalue-, , .

++


++ . '&podhd->line6' C++ , 'podhd' — .

WG21 (232. Is indirection through a null pointer undefined behavior?), . , . C++, «poldh->line6», «polhd» — .

«polhd» ( 5.2.5/4, ) , . C++ nullptr.


struct usb_line6 *line6 = &podhd->line6;

++, podhd 0. 0, .

, , . , . , , . , .

. .




, , . :


  1. Wikipedia. .
  2. A Guide to Undefined Behavior in C and C++. Part 1, 2, 3.
  3. Wikipedia. offsetof.
  4. LLVM Blog. What Every C Programmer Should Know About Undefined Behavior #2/3.
  5. LWN. Fun with NULL pointers. Part 1, 2.


Source: https://habr.com/ru/post/J250701/


All Articles