C奇怪的数组行为

时间:2010-05-14 18:54:30

标签: c arrays memcpy memset

在得知strncmp与我的操作系统(Linux)不同的strlcpy之后,我认为我可以尝试自己编写。

我发现了libc维护者Ulrich Drepper的一句话,他使用strlcpy发布了mempcpy的替代方案。我也没有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'

您可以在内部表示(创建的行insp())中看到混合了一些噪音,例如第一次复制后检查中的printf()格式字符串,以及外部0x01第二份副本。

字符串被完整地复制并正确处理太长的源字符串(让我们忽略将0作为长度传递给copy_string的可能问题,我现在将解决这个问题)。

但是为什么我的目的地里面有外来数组内容(来自格式字符串)?就好像目的地实际上是RESIZED以匹配新的长度。

4 个答案:

答案 0 :(得分:4)

字符串的结尾标有\ 0,之后的内存可以是任何内容,除非你的操作系统故意将它空白然后它就是那里留下的随机垃圾。

请注意,在这种情况下,'问题'不在copy_string中,你正在复制10chars - 但主代码中'first'之后的内存只是随机的。

答案 1 :(得分:2)

因为你没有停止在源大小,你停止在命运大小,这恰好比源大,所以你正在复制源字符串加上一点垃圾。

您可以轻松地看到您正在使用其null终结符复制源字符串。但是,由于你要记忆10个字节,并且“First”和“Second”两个字符串都短于10个字节,你还要复制额外的字节。

答案 2 :(得分:1)

如果memcpy(dest, src, n-1)dest的长度不是srcn-1的使用会调用未定义的行为。

例如,First\0的长度为六个字符,但您可以从中读取n-1(9)个字符;字符串文字末尾的内存内容是未定义的,当你读取内存时程序的行为也是如此。

答案 3 :(得分:0)

因为你已经将缓冲区大小传递给memcpy,所以会有额外的“东西”。它会复制那么多字符,即使源更短也是如此。

我做的事情有点不同:

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

strncpy不同,strncat定义为大多数人合理期望的工作方式。