2

次の不変条件を仮定できますか?

void foo(char *buf, size_t len) {
  // "buf" points to either an array or memory allocated with malloc().
  assert((uintptr_t)(buf + len) < UINTPTR_MAX);
}

私が書いているパーサーでは、ポインターを使用して特定のオフセットをマークしたいと考えています。たとえばchar *end_of_submessageend_of_submessageは現在のバッファーに相対的です。ただし、サブメッセージが現在のバッファー内で終了しない場合は、現在のバッファー内のオフセットよりも大きい値を使用したいと考えています。だから私はするだろう:

void parse(char *buf, size_t len, uintptr_t end_of_submessage) {
  // Some parsing that might increment "buf"
  // ...

  // If end_of_submessage == UINTPTR_MAX, processing will not be
  // triggered even if we have processed our entire current buffer.
  if ((uintptr_t)buf >= end_of_submessage)
    process_submsg_end();
}

ptr + len == UINTPTR_MAXしかし、malloc() が のようなメモリを返した場合、または配列が同じプロパティを持っていた場合、このスキームは阻止されます。これが決して起こらないと仮定しても安全ですか?規格上安全ですか?そうでない場合、実際には安全ですか?

4

1 に答える 1

5

C標準が提供する唯一の保証は次のとおりです。

ISO / IEC 9899:1999(E)§7.18.1.4/1

次の型は、voidへの有効なポインタをこの型に変換してから、voidへのポインタに戻すことができるというプロパティを持つ符号付き整数型を指定し、結果は元のポインタと同じになります。

intptr_t

次の型は、voidへの有効なポインタをこの型に変換してから、voidへのポインタに戻すことができるというプロパティを持つ符号なし整数型を指定し、結果は元のポインタと同じになります。

uintptr_t

これらのタイプはオプションです。

これらの変換された整数の正確な内容については保証されません。特に、charポインタが与えられた場合、 truep(uintptr_t)(p + 1) == ((uintptr_t)p) + 1あるとは限りません。

オフセットをマークする場合はptrdiff_t、別のポインターからのオフセットを使用するか、ポインターを使用して終了をマークすることができます。例えば:

void parse(char *buf, size_t len, char *end_of_submessage)
{
// ...
    if (buf >= end_of_submessage)
        process_submsg_end();
}

end_of_submessage別のバッファにある可能性がある場合は、次のようなものを使用できます。

char *buf_start = buf;
// ...
if (buf_start <= end_of_submessage && buf >= end_of_submessage)
  process_submsg_end();
于 2011-07-14T23:57:08.413 に答える