我无法运行此c代码。当我这样做时,我得到分段错误,并且错误地返回' return 0xdeadbeef;
有人有任何建议吗?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int lame(unsigned int size, unsigned int value){
unsigned int array1[4];
unsigned int array2[6];
array2[5] = value;
memcpy(&array1, &array2, size * sizeof(unsigned int));
return 1;
}
void awesome(){
printf("awwwwwww yeaaahhhhh! All awesome, all the time!\n");
}
main(unsigned int argc, char ** argv){
unsigned int size, value;
size = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 16);
if(!lame(size, value)){
awesome();
}
else{
printf("I am soooo lame :(\n");
}
return 0xdeadbeef;
}
答案 0 :(得分:2)
我说在你的代码的几乎每一行都有“至少一个bug”,现在我将列出它们。如果我对某一行没有任何评论,那么该行上就没有错误,但您还需要阅读正确的代码格式和样式。
int lame(unsigned int size, unsigned int value){
unsigned int array1[4];
unsigned int array2[6];
array2[5] = value;
memcpy(&array1, &array2, size * sizeof(unsigned int));
return 1;
}
如果memcpy
大于4,size
行上的未定义行为。由于size
来自用户输入,此程序包含缓冲区溢出漏洞,尽管可能很难利用。 (您需要阅读“Smashing the Stack for Fun and Profit。”)
此功能没有外部可见的副作用。除return 1
之外,编译器可能并且可能会删除所有代码。
应该重构始终返回相同常量值的函数以返回void
。在当前文件之外未使用的函数应声明为static
。
void awesome(){
printf("awwwwwww yeaaahhhhh! All awesome, all the time!\n");
}
printf
的使用可以由puts
替换。在当前文件之外未使用的函数应声明为static
。
main(unsigned int argc, char ** argv){
main
的第一个参数必须为int
,而不是unsigned int
。缺少返回类型(必须为int
,而不是void
);许多编译器会容忍这种情况(将其视为隐式返回int
)以便与C89之前的代码向后兼容,但它仍然是错误的。
unsigned int size, value;
size = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 16);
size
和value
都应为unsigned long
,以便与strtoul
返回的内容保持一致。
如果命令行参数少于两个,则为未定义的行为。
需要检查对strtoul
的两次调用是否失败。这非常重要;阅读EXAMPLES section of the OpenBSD manpage for strtoul
以了解如何正确。
但是,使用strtoul
而不是atoi
(无法检查失败)或sscanf
(在整数上有未定义的行为)的道具溢出)。
if(!lame(size, value)){
awesome();
}
else{
printf("I am soooo lame :(\n");
}
编译器可以并且将确定lame
始终返回1,并优化对awesome
的调用。 (事实上,它有权优化所有但上面的printf
,因为所有控制流路径都会触发未定义的行为或者它们到达printf
,并且没有其他外部可见效果。我很容易掌握的编译器并不那么聪明,但是他们做删除if-then-else和lame
内的所有代码。)
此printf
的使用也可以由puts
替换。
当你停止称自己为跛足时,你将自动减少23%的跛脚。
return 0xdeadbeef;
main
返回的值很有意义。 0表示整个程序的成功,任何其他值意味着某种失败。除非您打算指示失败,否则始终返回0。此外,父流程跨平台只能可靠地接收范围[0,127]中的值; 0xdeadbeef
是正确的。
在屏幕截图中,main
返回了void
,而不是丢失了返回类型;加上带有值的return
语句应该导致程序无法编译。但是,您的编译器可能会在main
中容忍它。