6

どちらもstrncmp見た目とはstrlcpy異なり、私のオペレーティング システム (Linux) では利用できないことを知った後、自分で書いてみようと思いました。

libc のメンテナーである Ulrich Drepper からの引用を見つけましstrlcpymempcpy。どちらも持っていませんがmempcpy、その動作は簡単に再現できました。まず、これは私が持っているテストケースです

#include <stdio.h>
#include <string.h>

#define BSIZE 10

void insp(const char* s, int n)
{
   int i;

   for (i = 0; i < n; i++)
      printf("%c  ", s[i]);

   printf("\n");

   for (i = 0; i < n; i++)
      printf("%02X ", s[i]);

   printf("\n");

   return;
}

int copy_string(char *dest, const char *src, int n)
{
   int r = strlen(memcpy(dest, src, n-1));
   dest[r] = 0;

   return r;
}

int main()
{
   char b[BSIZE];
   memset(b, 0, BSIZE);

   printf("Buffer size is %d", BSIZE);

   insp(b, BSIZE);

   printf("\nFirst copy:\n");
   copy_string(b, "First", BSIZE);
   insp(b, BSIZE);
   printf("b = '%s'\n", b);

   printf("\nSecond copy:\n");
   copy_string(b, "Second", BSIZE);
   insp(b, BSIZE);

   printf("b = '%s'\n", b);

   return 0;
}

そして、これがその結果です:

Buffer size is 10                    
00 00 00 00 00 00 00 00 00 00 

First copy:
F  i  r  s  t     b     =    
46 69 72 73 74 00 62 20 3D 00 
b = 'First'

Second copy:
S  e  c  o  n  d          
53 65 63 6F 6E 64 00 00 01 00 
b = 'Second'

内部表現 (作成された行)には、最初のコピー後の検査でのフォーマット文字列や、2 番目のコピーでの外部の 0x01 など、insp()ノイズが混入していることがわかります。printf()

文字列はそのままコピーされ、長すぎるソース文字列を正しく処理します (copy_stringここでは、長さとして 0 を渡すことで発生する可能性のある問題を無視しましょう。後で修正します)。

しかし、宛先内に (フォーマット文字列からの) 外部配列の内容があるのはなぜですか? あたかも宛先が新しい長さに一致するように実際にサイズ変更されたかのようです。

4

4 に答える 4

4

文字列の末尾は \0 でマークされ、その後のメモリは何でもかまいません。OS が意図的に空白にしない限り、ランダムなジャンクがそこに残っているだけです。

この場合、「問題」は copy_string にないことに注意してください。正確に 10 文字をコピーしていますが、メイン コードの「first」の後のメモリはランダムです。

于 2010-05-14T18:58:05.750 に答える
2

ソースサイズで停止していないため、たまたまソースよりも大きい運命のサイズで停止しているため、ソース文字列とそれを過ぎた少しのゴミをコピーしています。

null ターミネータを使用して、ソース文字列をコピーしていることは簡単にわかります。しかし、10 バイトを memcopy していて、"First" と "Second" の両方の文字列が 10 バイトより短いため、余分なバイトもコピーしています。

于 2010-05-14T18:58:37.903 に答える
1

と の両方が少なくとも長さ でない場合、 を使用すると、memcpy(dest, src, n-1)未定義の動作が呼び出されます。destsrcn-1

たとえば、First\0は 6 文字の長さですが、そこn-1から (9) 文字を読み取ります。文字列リテラルの末尾を超えるメモリの内容は、そのメモリを読み取るときのプログラムの動作と同様に未定義です。

于 2010-05-14T18:59:05.563 に答える
0

バッファサイズを に渡したので、余分な「もの」がありますmemcpy。ソースが短い場合でも、それだけ多くの文字をコピーします。

私は少し違うことをします:

void copy_string(char *dest, char const *src, size_t n) { 
    *dest = '\0';
    strncat(dest, src, n);
}

とは異なりstrncpystrncatほとんどの人が合理的に期待する方法で動作するように定義されています。

于 2010-05-14T19:02:53.170 に答える