第5章 補足
5.1. コンパイラーおよび開発ツールにおける互換性に影響を与える変更点
非定数の PTHREAD_STACK_MIN
、MINSIGSTKSZ
、および SIGSTKSZ
マクロ
スケーラブルベクトルレジスターの可変スタックサイズを必要とするアーキテクチャーのサポートを向上するために、PTHREAD_STACK_MIN
、MINSIGSTKSZ
、および SIGSTKSZ
マクロの定数値が、非定数値 (sysconf
呼び出しなど) に変更されました。
PTHREAD_STACK_MIN
、MINSIGSTKSZ
、および SIGSTKSZ
マクロを定数値のように扱う方法は、使用できなくなりました。PTHREAD_STACK_MIN
、MINSIGSTKSZ
、および SIGSTKSZ
マクロに対して返される値は、long データ型になり、符号なしの値 (size_t
など) と比較するとコンパイラー警告が発生する可能性があります。
libc.so.6
にマージされたライブラリー
この更新により、次のライブラリーが libc
ライブラリーにマージされました。これにより、スムーズなインプレースアップグレードエクスペリエンスを実現し、プロセスによるスレッドの安全な随時使用をサポートし、内部実装を簡素化します。
-
libpthread
-
libdl
-
libutil
-
libanl
さらに、Name Switch Service (NSS) ファイルと Domain Name System (DNS) プラグインの libc
ライブラリーへの直接移動をサポートするために、libresolv
ライブラリーの一部が libc に移動されました。NSS ファイルと DNS プラグインは、libc
ライブラリーに直接組み込まれ、アップグレード時に、または chroot
やコンテナーの境界を越えて使用できるようになりました。chroot
またはコンテナーの境界を越えてこれらを使用すると、これらのソースからの Identity Management (IdM) データの安全なクエリーがサポートされます。
zdump
ユーティリティーの場所変更
zdump
ユーティリティーの場所が /usr/bin/zdump
に変更されました。
sys_siglist
、_sys_siglist
、および sys_sigabbrev
シンボルの非推奨化
sys_siglist
、_sys_siglist
、および sys_sigabbrev
シンボルは、古いバイナリーをサポートするための互換性シンボルとしてのみエクスポートされます。すべてのプログラムで、代わりに strsignal
シンボルを使用する必要があります。
sys_siglist
、_sys_siglist
、および sys_sigabbrev
シンボルを使用すると、配列アクセスに対する明示的な境界チェックがないため、コピーの再配置や、エラーが発生しやすいアプリケーションバイナリーインターフェイス (ABI) などの問題が発生します。
この変更は、一部のパッケージのソースからのビルドに影響を与える可能性があります。この問題を解決するには、代わりに strsignal
シンボルを使用するようにプログラムを書き直します。以下に例を示します。
#include <signal.h> #include <stdio.h> static const char *strsig (int sig) { return sys_siglist[sig]; } int main (int argc, char *argv[]) { printf ("%s\n", strsig (SIGINT)); return 0; }
#include <signal.h>
#include <stdio.h>
static const char *strsig (int sig)
{
return sys_siglist[sig];
}
int main (int argc, char *argv[])
{
printf ("%s\n", strsig (SIGINT));
return 0;
}
以下のように調整する必要があります。
#include <signal.h> #include <stdio.h> #include <string.h> static const char *strsig (int sig) { return strsignal(sig); } int main (int argc, char *argv[]) { printf ("%s\n", strsig (SIGINT)); return 0; }
#include <signal.h>
#include <stdio.h>
#include <string.h>
static const char *strsig (int sig)
{
return strsignal(sig);
}
int main (int argc, char *argv[])
{
printf ("%s\n", strsig (SIGINT));
return 0;
}
または、glibc-2.32
GNU 拡張の sigabbrev_np
または sigdescr_np
を使用するには、次のようにします。
#define _GNU_SOURCE #include <signal.h> #include <stdio.h> #include <string.h> static const char *strsig (int sig) { const char *r = sigdescr_np (sig); return r == NULL ? "Unknown signal" : r; } int main (int argc, char *argv[]) { printf ("%s\n", strsig (SIGINT)); printf ("%s\n", strsig (-1)); return 0; }
#define _GNU_SOURCE
#include <signal.h>
#include <stdio.h>
#include <string.h>
static const char *strsig (int sig)
{
const char *r = sigdescr_np (sig);
return r == NULL ? "Unknown signal" : r;
}
int main (int argc, char *argv[])
{
printf ("%s\n", strsig (SIGINT));
printf ("%s\n", strsig (-1));
return 0;
}
どちらの拡張も、非同期シグナルセーフおよびマルチスレッドセーフです。
sys_errlist
、_sys_errlist
、sys_nerr
、および _sys_nerr
シンボルの非推奨化
sys_errlist
、_sys_errlist
、sys_nerr
、および _sys_nerr
シンボルは、古いバイナリーをサポートするための互換性シンボルとしてのみエクスポートされます。すべてのプログラムで、代わりに strerror
または strerror_r
シンボルを使用する必要があります。
sys_errlist
、_sys_errlist
、sys_nerr
、および _sys_nerr
シンボルを使用すると、配列アクセスに対する明示的な境界チェックがないため、コピーの再配置や、エラーが発生しやすい ABI などの問題が発生します。
この変更は、一部のパッケージのソースからのビルドに影響を与える可能性があります。この問題を解決するには、strerror
または strerror_r
シンボルを使用してプログラムを書き直します。以下に例を示します。
#include <stdio.h> #include <errno.h> static const char *strerr (int err) { if (err < 0 || err > sys_nerr) return "Unknown"; return sys_errlist[err]; } int main (int argc, char *argv[]) { printf ("%s\n", strerr (-1)); printf ("%s\n", strerr (EINVAL)); return 0; }
#include <stdio.h>
#include <errno.h>
static const char *strerr (int err)
{
if (err < 0 || err > sys_nerr)
return "Unknown";
return sys_errlist[err];
}
int main (int argc, char *argv[])
{
printf ("%s\n", strerr (-1));
printf ("%s\n", strerr (EINVAL));
return 0;
}
以下のように調整する必要があります。
#include <stdio.h> #include <errno.h> static const char *strerr (int err) { return strerror (err); } int main (int argc, char *argv[]) { printf ("%s\n", strerr (-1)); printf ("%s\n", strerr (EINVAL)); return 0; }
#include <stdio.h>
#include <errno.h>
static const char *strerr (int err)
{
return strerror (err);
}
int main (int argc, char *argv[])
{
printf ("%s\n", strerr (-1));
printf ("%s\n", strerr (EINVAL));
return 0;
}
または、glibc-2.32
GNU 拡張の strerrorname_np
または strerrordesc_np
を使用するには、次のようにします。
#define _GNU_SOURCE #include <stdio.h> #include <errno.h> #include <string.h> static const char *strerr (int err) { const char *r = strerrordesc_np (err); return r == NULL ? "Unknown error" : r; } int main (int argc, char *argv[]) { printf ("%s\n", strerr (-1)); printf ("%s\n", strerr (EINVAL)); return 0; }
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <string.h>
static const char *strerr (int err)
{
const char *r = strerrordesc_np (err);
return r == NULL ? "Unknown error" : r;
}
int main (int argc, char *argv[])
{
printf ("%s\n", strerr (-1));
printf ("%s\n", strerr (EINVAL));
return 0;
}
どちらの拡張も、非同期シグナルセーフおよびマルチスレッドセーフです。
ユーザー空間メモリーアロケーター、malloc
の変更
mallwatch
および tr_break
シンボルは非推奨になり、mtrace
関数では使用されなくなりました。GDB 内の mtrace
関数内で条件付きブレークポイントを使用すると、同様の機能を実現できます。
__morecore
および __after_morecore_hook
malloc
フックとデフォルトの実装 __default_morecore
は、API から削除されました。既存のアプリケーションは引き続きこれらのシンボルに対してリンクしますが、インターフェイスは malloc
に影響を与えなくなります。
MALLOC_CHECK_
環境変数 (または glibc.malloc.check
調整可能パラメーター)、mtrace()
、および mcheck()
などの malloc
のデバッグ機能は、メイン C ライブラリーでデフォルトで無効になりました。これらの機能を使用するには、新しい libc_malloc_debug.so
デバッグ DSO をプリロードします。
非推奨の関数 malloc_get_state
および malloc_set_state
は、コア C ライブラリーから libc_malloc_debug.so
ライブラリーに移動されました。これらの関数をまだ使用しているレガシーアプリケーションでは、LD_PRELOAD
環境変数を使用して環境に libc_malloc_debug.so
ライブラリーをプリロードする必要があります。
非推奨のメモリー割り当てフック __malloc_hook
、__realloc_hook
、__memalign_hook
、および __free_hook
は、API から削除されました。互換性シンボルはレガシープログラムをサポートするために存在しますが、新しいアプリケーションはこれらのシンボルにリンクできなくなりました。これらのフックは、glibc
の機能に影響を与えなくなりました。malloc
のデバッグ DSO libc_malloc_debug.so
は、現在フックをサポートしています。これをプリロードすることで、古いプログラムでこの機能を復元できます。ただし、これは過渡的な措置であり、GNU C ライブラリーの今後のリリースでは削除される可能性があります。独自の malloc
割り込みライブラリーを作成してプリロードすることで、これらのフックから移植できます。
遅延結合の失敗によるプロセスの終了
ELF コンストラクターの実行中に、dlopen
関数で遅延結合の失敗が発生した場合、プロセスが終了します。以前は、動的ローダーが dlopen
から NULL
を返し、遅延結合エラーが dlerror
メッセージでキャプチャーされていました。一般に、任意の関数呼び出しでスタックをリセットすることはできないため、これは安全ではありません。
stime
関数の非推奨化
stime
関数は、新しくリンクされたバイナリーでは使用できなくなり、その宣言が <time.h>
から削除されました。システム時間を設定するプログラムには、代わりに clock_settime
関数を使用してください。
popen
関数と system
関数が atfork
ハンドラーを実行しなくなる
これは POSIX 違反の可能性がありますが、atfork
ハンドラーに関する pthread_atfork
ドキュメントに記載されている POSIX の根拠は、マルチスレッドプロセスでの fork 呼び出し後の整合性のないミューテックス状態を処理することです。popen
関数でも system
関数でも、ユーザー定義のミューテックスに直接アクセスすることはできません。
C++ 標準ライブラリーの非推奨機能
-
std::string::reserve(n)
が、文字列の現在の容量よりも小さい引数を使用して呼び出された場合に、文字列の容量を削減しなくなりました。引数なしでreserve()
を呼び出すことで文字列の容量を減らすことができますが、そのような形式は非推奨です。代わりに、同等のshrin_to_fit()
を使用してください。 -
非標準の
std::__is_nullptr_t
型特性は非推奨になりました。代わりに、標準のstd::is_null_pointer
特性を使用してください。