4
__inline int my_sprintf (char *dest,char *format,...)
{
    va_list va;
    va_start(va,format);
    return vsprintf(dest,format,va);
}

私の問題は、バッファ サイズ パラメータを my_sprintf に追加できないことです。これは、5 万を超える場所で使用されているためです。vsprintf を vsprintf_s または vsnprintf に置き換えることはできません。

上記の機能をより安全にするための代替手段はありますか?

4

6 に答える 6

5

ここであなたが求めているのは、(悪名高い) 有名な質問の特殊化です: 「私が持っているのがポインターしかない場合、配列のサイズを取得する方法は?

が指すオブジェクトのサイズを把握する方法はありませんdest。あなたの最善の選択肢は、弾丸を噛んで、それらの 50k の場所を変更してサイズを渡すことです。


あなたのコードには、あなたが私たちに伝えていないことがもっとあるかもしれません。たとえば、あなたが言及した「50k」の場所では、サイズはわかっていますか? もしそうならsizeof、舞台裏で使用し、長さパラメータを取る関数を呼び出すダーティな可変引数マクロを回避できます。

于 2015-05-28T14:51:36.243 に答える
2

OPは「多数のバッファが動的に割り当てられます...」とコメントしました。、malloc()realloc()、などはcalloc()free()サイズを格納するラッパー関数で書き直すことができます。

typedef union {
  max_align_t align;
  size_t sz;
} my_header;

void* my_malloc(size_t size) {
  my_header *p = malloc(sizeof *p + size);
  if (p) {
    p->sz = size;
    p++;
  }
  return p;
}

size_t my_size(const void *p) {
  if (p) {
    const my_header *head = p;
    return head[-1].sz;
  }
  return 0;
}

void my_free(void *p) {
  if (p) {
    my_header *head = p;
    free(--head);
  }
}

他のすべての*.c ファイルは、いくつかの *.h ファイルを次のように呼び出します。

#define malloc my_malloc
#define free my_free
void *my_malloc(size_t size);
void my_free(void *p);
size_t my_size(const void *p);

、割り当てられたポインターmy_sprintf()で呼び出されると...

int my_sprintf (char *dest,char *format,...) {
  va_list va;
  va_start(va,format);
  size_t n = my_size(dest);
  return vsnprintf(dest,n,format,va);
}

さらに、渡されたポインターが本当に 1 であるかどうかを識別するために、マジック ナンバーmy_allcoated()を前に追加することもできます。

割り当て関数をラップすることは、さまざまな割り当ての問題を判断する方法でもあります: 二重解放、最大使用量、すべてのポインターの解放など。


[編集] 5年後。

コードはアライメントを確保する必要があります - コードは作り直されました。


C11 より前のバージョンでは、 の代わりにワイド型の共用体を使用しますmax_align_t

typedef union {
  double d;
  long l;
  void *p;
  void (*fp)();
  // With C99
  complex long double cld;
  long long ll;

  size_t sz;
} my_header; 
于 2015-05-28T17:07:22.757 に答える