Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
调试C中的堆栈溢出?_C_Debugging_Gdb_Stack Overflow - Fatal编程技术网

调试C中的堆栈溢出?

调试C中的堆栈溢出?,c,debugging,gdb,stack-overflow,C,Debugging,Gdb,Stack Overflow,我有一个示例程序,当使用fstack protector编译时,它会导致堆栈崩溃 #include <stdio.h> #include <stdint.h> int func(int* value) { uint8_t port = 1; *value = port; //Canary value changes at this point when seen in GDB return 1; } int main() { ui

我有一个示例程序,当使用fstack protector编译时,它会导致堆栈崩溃

#include <stdio.h>
#include <stdint.h>


int func(int* value)
{
    uint8_t port = 1;

    *value = port; //Canary value changes at this point when seen in GDB

    return 1;
}

int main()
{
    uint16_t index = 0;

    int ret = func((int*)&index);

}
#包括
#包括
int func(int*值)
{
uint8_t端口=1;
*value=port;//当在GDB中看到时,金丝雀的值在此时发生变化
返回1;
}
int main()
{
uint16_t指数=0;
int ret=func((int*)和index);
}

我不明白这条线怎么了。需要任何类型转换吗?

这是因为
int
int16\t
的大小不同。
int
的大小(通常)是32位(四个字节),而
int16\u t
的大小是16位(两个字节)

因此,当您将
int
写入
int16\t
变量时,您写入的字节太多,导致(在这种情况下,将“粉碎”堆栈)


问题更具体地说是因为您使用指向
index
的指针调用函数,该指针是一个16位变量,但函数期望(并使用其参数)作为32位变量。您不应该在调用中进行转换,因为这会隐藏问题,但不会解决问题。只向函数内的解引用指针写入8位值并不重要,目标仍然是32位变量,编译器将在写入内存之前将8位值转换为32位值。

这是因为
int
int16\t
的大小不同。
int
的大小(通常)是32位(四个字节),而
int16\u t
的大小是16位(两个字节)

因此,当您将
int
写入
int16\t
变量时,您写入的字节太多,导致(在这种情况下,将“粉碎”堆栈)


问题更具体地说是因为您使用指向
index
的指针调用函数,该指针是一个16位变量,但函数期望(并使用其参数)作为32位变量。您不应该在调用中进行转换,因为这会隐藏问题,但不会解决问题。只向函数内的解引用指针写入8位值并不重要,目标仍然是32位变量,编译器将在写入内存之前将8位值转换为32位值。

由于
索引的类型是
uint16\u t
,因此只为其分配16位。通过将
索引
的地址强制转换为
int*
,可以假装您可以访问超过16位的数据,在大多数情况下是32位


您正试图在尚未分配的位中设置值。由于该行中使用了未经授权的内存,此后可能会发生任何事情。

由于
索引的类型是
uint16\t
,因此只为其分配了16位。通过将
索引
的地址强制转换为
int*
,可以假装您可以访问超过16位的数据,在大多数情况下是32位



您正试图在尚未分配的位中设置值。由于该行使用了未经授权的内存,因此在此之后可能会发生任何事情。

我认为在这行“*value=port;”,uint8\u t写入int。int在哪里写入u16?但他在哪里写入int到int16\u t?@IDK将指向
int16\u t
的指针传递给函数,但函数需要指向
int
的指针。这就是问题所在。我想你在电话中添加了类型转换只是因为你收到了警告?警告通常是你做了不该做的事情的标志,用类型转换隐藏它只是隐藏了问题,但并不能解决问题。@IDK:因为
value
int*
,所以
uint8\u t
在存储之前会转换成
int
。我现在明白了。谢谢!我认为在这行“*value=port;”,uint8\u t写入int。int在哪里写入u16?但他在哪里写入int到int16\u t?@IDK将指向
int16\u t
的指针传递给函数,但函数需要指向
int
的指针。这就是问题所在。我想你在电话中添加了类型转换只是因为你收到了警告?警告通常是你做了不该做的事情的标志,用类型转换隐藏它只是隐藏了问题,但并不能解决问题。@IDK:因为
value
int*
,所以
uint8\u t
在存储之前会转换成
int
。我现在明白了。谢谢!尽管我看到了这个问题的答案,但我无法重现任何错误。我确实做了
gcc-fstack protector yourcode.c
。很抱歉,旗子是-fstack保护者allI也试过了。仍然编译得很好。而且跑得也很好,真奇怪。我被全旗扣杀了。看看gdb中的金丝雀值是否发生变化。这是一个关于如何通过无意义地四处抛投来击打自己脚的好例子。尽管我看到了这个问题的答案,但我无法重现任何错误。我做了
gcc-fstack protector yourcode.c
。很抱歉,旗子是-fstack保护者allI也试过了。仍然编译得很好。而且跑得也很好,真奇怪。我被全旗扣杀了。看看gdb中的金丝雀值是否发生变化。这是另一个关于如何通过无意义的抛投射中自己脚的好例子。
*value = port;