【问题标题】:copy character string to an unsigned buffer: Segmentation fault将字符串复制到无符号缓冲区:分段错误
【发布时间】:2011-08-14 07:24:39
【问题描述】:

我正在尝试将两个整数和一个字符串复制到缓冲区并打印出缓冲区元素。第三个 printf 语句出现段错误:

    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];

我不知道为什么会出现段错误?

【问题讨论】:

  • 什么是缓冲区,两个“f”声明为 -- 你说缓冲区是无符号字符[444]
  • stringstr是如何声明的?

标签: c segmentation-fault buffer memmove


【解决方案1】:

buffer[8] 是一个char%s 等待字符串,意思是char *,而是通过&buffer[8]。您会遇到分段错误,因为 printf 试图将 char 视为 指向 char 的指针,它是地址(如果传递了 char,则它不太可能是有效的)

编辑:正如 David 所评论的,如果复制字符串的起点与其之前的值有关,请不要使用固定值,而不是 &buffer[8] 使用 buffer+(2*sizeof(id))buffer[2*sizeof(id)]

【讨论】:

  • +1,虽然buffer+8 或更好,但buffer+2*sizeof (int) 会更好
【解决方案2】:

您的代码有几个问题,但最重要的一点是memmove() 没有复制字符串的空字符字节。

The function 不检查源中的任何终止空字符 - 它总是精确复制 num 个字节。

这为您提供了两种选择:

  • 在复制内容时考虑一下:

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]);

【讨论】:

  • 很好的解释。多谢。我忘了使用 strlen 并考虑空字符
【解决方案3】:

主要问题是您试图通过仅传递一个字符来打印字符串。这是因为 buffer[8] 指的是索引 8 处的 char,而不是从该位置开始的字符串。所以你需要把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’

不应忽视警告!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 2015-10-29
    • 2012-07-17
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    • 2016-03-09
    相关资源
    最近更新 更多