C 为什么会发生缓冲区溢出? #包括 无效ft\u rev\u int\u选项卡(int*选项卡,int大小) { int*rev_选项卡; int*ptab; ptab=tab; 版次=制表符+尺寸; while(rev_tab!=ptab) { *rev_tab--=*tab++; printf(“%d\n”,*rev\u选项卡); } printf(“%d”,*rev_选项卡); } int main() {int数组[10]={0,1,2,3,4,5,6,7,8,9}; ft_rev_int_tab(数组,10); 返回0; }
我创建了一个反转给定整数数组的函数C 为什么会发生缓冲区溢出? #包括 无效ft\u rev\u int\u选项卡(int*选项卡,int大小) { int*rev_选项卡; int*ptab; ptab=tab; 版次=制表符+尺寸; while(rev_tab!=ptab) { *rev_tab--=*tab++; printf(“%d\n”,*rev\u选项卡); } printf(“%d”,*rev_选项卡); } int main() {int数组[10]={0,1,2,3,4,5,6,7,8,9}; ft_rev_int_tab(数组,10); 返回0; },c,pointers,C,Pointers,我创建了一个反转给定整数数组的函数 但是他们显示了这个错误。如果我在linux上命令./a.out | cat-e, 他们显示 如果我命令的话。/a.它们会显示出来 为什么linux显示出使用cat-e和不使用cat-e的区别? 如果我把数组的大小设为奇数,就不会有错误! 为什么会发生这种情况?修复内存损坏 错误消息表示您的程序因中止信号而崩溃。这可能是内存损坏的结果。内存损坏往往会导致未定义的行为。因此,如果您的程序内存损坏,那么您的程序有时会崩溃,有时工作正常。你的例子就是这样。您的问题
但是他们显示了这个错误。如果我在linux上命令./a.out | cat-e, 他们显示 如果我命令的话。/a.它们会显示出来 为什么linux显示出使用cat-e和不使用cat-e的区别? 如果我把数组的大小设为奇数,就不会有错误! 为什么会发生这种情况?修复内存损坏 错误消息表示您的程序因中止信号而崩溃。这可能是内存损坏的结果。内存损坏往往会导致未定义的行为。因此,如果您的程序内存损坏,那么您的程序有时会崩溃,有时工作正常。你的例子就是这样。您的问题与
cat-e
无关,只有运气好,当您在没有cat-e
的情况下调用它时,您的程序才能正常工作。如果再运行几次程序,最终会看到另一次崩溃
在您的程序中,以下行导致内存损坏:
#include <stdio.h>
void ft_rev_int_tab(int *tab, int size)
{
int *rev_tab;
int *ptab;
ptab = tab;
rev_tab = tab + size ;
while (rev_tab != ptab)
{
*rev_tab-- = *tab++;
printf("%d\n",*rev_tab);
}
printf("%d", *rev_tab);
}
int main()
{ int array[10] = {0,1,2,3,4,5,6,7,8,9};
ft_rev_int_tab(array, 10);
return 0;
}
表达式rev_选项卡--
是一个。修复后减量将变量减少1,并返回旧值。因此,例如,如果rev_tab
是指向内存位置100000
的指针,您可以运行以下行:
*rev_tab-- = *tab++;
然后在该行之后,rev_tab
是99999
,但是result
收到了旧值100000
因此,在您的程序中,rev_tab
最初指向rev_tab=tab+size
,这是紧跟在表之后的内存位置(即,表中的最后一个内存位置是tab+size-1
。同样,ptab=tab;
使ptab
指向表中的第一个内存位置。因此,当您执行*revu tab-->=*tab++;
时,即使revu tab--
将revu tab
减少1,也意味着它现在指向最后一个内存在表中的位置,表达式rev_tab--
的计算结果为rev_tab
的上一个值,因此*rev_tab--
将取消引用指向表后面的内存位置的指针。然后将*tab++
的结果写入该内存位置。这是一个缓冲区溢出,其结果是在未定义的行为中,由于进程的任意内存可能被覆盖,导致内存损坏。程序可能会崩溃,也可能不会崩溃,这取决于损坏的严重程度
因此,要解决此问题,您应该使用:
这将修复内存损坏,避免崩溃
我建议您在调试期间启用以检测此类内存问题。如果您使用GCC或Clang,您可以通过使用-fsanize=Address
编译来启用地址清理,这将在应用于原始程序时为您提供以下输出:
*--rev_tab = *tab++;
其他问题
在您的问题中,您声明要反转输入数组。但是,您发布的代码无法完成此任务。您有两个指针,一个指向数组的前面,一个指向数组的后面。然后循环,递增前指针,递减后指针,直到后指针到达第一个元素在迭代的每一步中,您都会将前指针引用的值写入后指针。但是,您不会将后指针引用的值写入前指针。因此,当遍历数组的后半部分时,它会被前半部分的值覆盖,但会被lat中的值覆盖上半部分没有写入上半部分,因此它们丢失。然后继续遍历上半部分,将写入下半部分的值写入上半部分。因此,当输入数组包含
0,1,2,3,4,5
时,结果将是0,1,2,2,1,0
。这不是您想要的结果。请删除zs>h标记。您的问题与zsh无关。谢谢您的帮助。我了解如何使用C处理内存,我还感谢您了解新的调试器!行不是应该吗,但后半部分的值没有写入后半部分,因此它们丢失了。更改为,但后半部分的值没有写入上半场,他们输了。?@user13145713你是对的,谢谢你指出我的错误。我现在已经更正了我的答案。
*--rev_tab = *tab++;
$ gcc -fsanitize=address -g test.c
$ ./a.out
=================================================================
==4848==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe3396f688 at pc 0x562ef80e528a bp 0x7ffe3396f5e0 sp 0x7ffe3396f5d0
WRITE of size 4 at 0x7ffe3396f688 thread T0
#0 0x562ef80e5289 in ft_rev_int_tab test.c:10
#1 0x562ef80e5659 in main test.c:17
#2 0x7f6dbecf8b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
#3 0x562ef80e50fd in _start (a.out+0x10fd)