将字符字符串复制到未签名的缓冲区:分段故障
-
25-10-2019 - |
题
我正在尝试将两个整数和一个字符串复制到缓冲区,并将缓冲元素打印出来。我得到第三个printf语句的SEG错误:
id = 102;
len = 3;
str = "working";
memmove(buffer,&message_id,sizeof(id));
memmove(buffer+(sizeof(id)),&len,sizeof(len));
memmove(buffer+(2*sizeof(id)),&string, sizeof(str));
printf("1 is: %d\n", buffer[0]);
printf("2 is: %d\n", buffer[4]);
printf("3 is %s\n, buffer[8])); // here is where i get the seg fault should
be a string
/***/
bufer is declared as unsinged char buffer[444];
我不知道为什么这会出现错误?
解决方案
您的代码上有几个问题,但最重要的一点是 memmove()
不复制字符串的空字节。
功能 不检查源中的任何终止零字符 - 它始终会精确复制数字字节。
这为您提供了两个选择:
- 在您复制这些内容时为此说明:
memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str) +1);
- 或复制内存后,请确保字符串以
'\0'
(又名。0
)在您的缓冲区上:
memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str));
buffer[sizeof(id)+ sizeof(len) + strlen(str) + 1] = 0;
无论如何,代码现在可以工作。另一个问题是您试图用 sizeof(str)
. 。那是错误的,你应该做 strlen(str)
. 。最后一件事,为了清晰和安全目的不做 2*sizeof(id)
. 。如果以后您决定更改拧紧的变量类型。正确的方式是 sizeof(id)+sizeof(len)
. 。就这样。
int id = 102;
int len = 3;
char* str = "working";
char buffer[444];
memmove(buffer,&id,sizeof(id));
memmove(buffer+(sizeof(id)), &len, sizeof(len));
memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str));
buffer[sizeof(id)+ sizeof(len) + strlen(str) + 1] = 0;
printf("1 is: %d\n", buffer[0]);
printf("2 is: %d\n", buffer[4]);
printf("3 is: %s\n", &buffer[8]);
其他提示
buffer[8]
是一个 char
, %s
等待字符串,含义 char *
, , 经过 &buffer[8]
反而。您会得到细分错误,因为printf试图治疗 char 作为一个 指向char, ,这是地址(如果通过字符,则不太可能是有效的)
编辑:AS 大卫 注释,如果复制字符串与之前的值相关的起点,请不要使用固定值,而不是 &buffer[8]
利用 buffer+(2*sizeof(id))
或者 buffer[2*sizeof(id)]
主要问题是您试图通过仅传递一个字符来打印字符串。这是因为 buffer[8]
指的是 char
在索引8处,不是从该位置开始的字符串。因此,您需要接受 buffer[8]
使其成为字符串或 char*
.
它之所以发挥作用的原因是 printf
尝试打印从第一个字符(即字符串内容本身)开始的地址开始的字符串,这不是有效的指针。
还有很多错别字和错误。工作版本如下:
#include <stdio.h>
#include <memory.h>
int main()
{
unsigned char buffer[444];
int id = 102;
int len = 3;
char* str = "working";
memmove(buffer,&id,sizeof(id));
memmove(buffer+(sizeof(id)),&len,sizeof(len));
memmove(buffer+(2*sizeof(id)), str, sizeof(str));
printf("1 is: %d\n", buffer[0]);
printf("2 is: %d\n", buffer[4]);
printf("3 is %s\n", &buffer[8]);
return 0;
}
如果您已编译了此应用程序并启用了所有警告(即。 -Wall
),您的编译器(至少是GCC确实)应该警告您这样的错误:
problem.c:18: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
警告不应被忽略!