为什么从以下代码中删除sprintf()会导致分段错误?如何处理它?

时间:2013-05-03 12:07:06

标签: c linux printf

我打算从我的代码中移除sprintf(),因为我的代码中不再需要它。但是当我这样做时,它会导致分段错误,而当sprintf()存在时它会正常工作请告诉我原因,以及如何解决这个问题。

unsigned char status_str[40]={0};
sprintf(status_str,"found HTTP:%dth time\n",(count+1));

2 个答案:

答案 0 :(得分:1)

首先,不推荐使用sprintf(3)(或者至少不推荐使用,请参阅链接手册页的 BUGS 部分),这是一个危险的函数(因为可能存在缓冲区溢出) 。您应该使用snprintf(这是自C99以来的标准,即自上个世纪以来)和代码

snprintf (status_str, sizeof(status_str), 
          "found HTTP:%dth time\n", (count+1));

snprintf优于sprintf的原因是,即使输出溢出缓冲区,snprintf也不会溢出给定的大小,而sprintf },不知道任何大小限制,将溢出。

然后,如果您的sprintf避免了某些细分错误(假设它没有溢出status_str),那么您已经被其他地方的某些undefined behavior 所伤害

我会想象,sprintf可能会填充一些未初始化的值的堆栈位置,而某些东西恰好会让它在以后运行。

我建议使用-Wall -Wextra -g进行编译(在没有警告的情况下改进代码)并使用gdb调试器(其watch命令很有帮助)。您还可以使用valgrind来搜寻内存泄漏(以及某些未初始化的访问权限)。

如果您需要更多帮助,请显示更多源代码。

使用GNU libc,您还可以使用asprintf来分配和填充一些堆 - malloc - 区域。这个函数是特定于GNU的(你应该确保指针是free - d稍后)。

答案 1 :(得分:1)

它到底在哪里?如果你真的只是删除它并且代码不再引用status_str那么它可能表明堆栈损坏。错误可能在某个地方发生,并且随机工作,但是当堆栈布局发生变化时,代码中看似无关的部分可能会因为没有明显原因而中断。

例如:如果较早的代码用一些值覆盖堆栈,并且这些值到达status_str,则不会造成任何损害,但是当它消失时,会覆盖其他内容,这可能会导致段错误。

但这只是一个猜测。因此,您应该检查在调用特定函数之前调用的代码。

澄清:它可以是任何内存,而不是堆栈的必要内容,取决于它的定义位置。