我的程序在不同的机器上给出不同的输出
My program is giving different output on different machines..!
#include<iostream>
#include<string.h>
#include<stdio.h>
int main()
{
char left[4];
for(int i=0; i<4; i++)
{
left[i]='0';
}
char str[10];
gets(str);
strcat(left,str);
puts(left);
return 0;
}
对于任何输入,它都应该将 0000 与该字符串连接起来,但在一台 PC 上,它在"0000"和输入字符串之间显示菱形符号...!
将可能的九个(或更多,gets
没有边界检查(字符串附加到三个字符串(包含四个字符,没有字符串终止符(。完全没有字符串终止。因此,当您使用 puts
打印时,它将继续打印,直到找到字符串终止字符,该字符可能位于内存中的任何位置。简而言之,这是缓冲区溢出的教科书示例,缓冲区溢出通常会导致您所看到的未定义的行为。
在 C 和 C++ 中,必须终止所有 C 样式字符串。它们由特殊字符终止:' '
(或纯 ASCII 零(。还需要在strcat
调用中为目标字符串提供足够的空间。
适当的工作计划:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void)
{
/* Size is 4 + 10 + 1, the last +1 for the string terminator */
char left[15] = "0000";
/* The initialization above sets the four first characters to '0'
* and properly terminates it by adding the (invisible) ' ' terminator
* which is included in the literal string.
*/
/* Space for ten characters, plus terminator */
char str[11];
/* Read string from user, with bounds-checking.
* Also check that something was truly read, as `fgets` returns
* `NULL` on error or other failure to read.
*/
if (fgets(str, sizeof(str), stdin) == NULL)
{
/* There might be an error */
if (ferror(stdin))
printf("Error reading input: %sn", strerror(errno));
return 1;
}
/* Unfortunately `fgets` may leave the newline in the input string
* so we have to remove it.
* This is done by changing the newline to the string terminator.
*
* First check that the newline really is there though. This is done
* by first making sure there is something in the string (using `strlen`)
* and then to check if the last character is a newline. The use of `-1`
* is because strings like arrays starts their indexing at zero.
*/
if (strlen(str) > 0 && str[strlen(str) - 1] == 'n')
str[strlen(str) - 1] = ' ';
/* Here we know that `left` is currently four characters, and that `str`
* is at most ten characters (not including zero terminaton). Since the
* total length allocated for `left` is 15, we know that there is enough
* space in `left` to have `str` added to it.
*/
strcat(left, str);
/* Print the string */
printf("%sn", left);
return 0;
}
代码中有两个问题。
首先,left
不是以 nul 结尾终止的,因此strcat
最终会在数组末尾之外查找附加字符的适当位置。在数组的末尾放一个' '
。
其次,left
不够大,无法容纳调用strcat
的结果。必须有足够的空间来容纳生成的字符串,包括 NUL 终止符。因此,left
的大小应至少为 4 + 9,以允许left
开头的三个字符(加上 nul 终止符(和来自str
的 9 个字符(假设gets
没有导致溢出(。
这些错误中的每一个都会导致未定义的行为,这解释了不同平台上的不同结果。
你为什么要费心包含<iostream>
,因为你没有在代码中使用任何C++功能。 如果您有以下条件,您的整个程序会短得多:
#include <iostream>
#include <string>
int main()
{
std::string line;
std::cin >> line;
std::cout << "You entered: " << line;
return 0;
}
由于std::string
将以空值终止,因此没有理由强制其以 4 空终止。
问题 #1 - 不是合法字符串:
char left[4];
for(int i=0; i<4; i++)
{
left[i]='0';
}
字符串必须以零字符结尾,' '
不能'0'
。这会导致您所描述的内容。
问题 #2 - fgets
.您可以在一个小缓冲区上使用它。非常危险。
问题 #3 - strcat
.再次尝试用额外的字符串填充一个应该已经填满的超小缓冲区。
此代码看起来像是缓冲区溢出攻击的邀请。
在 C 中,我们所说的字符串是一个以 null 结尾的字符数组。string.h 库中的所有函数都基于字符数组末尾的此 null。你的字符数组不是以null结尾的,因此不是字符串,所以这里不能使用字符串库函数strcat。
- 递归函数计算序列中的平方和(并输出过程)
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 请解释"函数1(p1,p2,p3);"的输出
- C++:将控制台输出存储在宏中更好吗
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 为什么我的代码在输出中增加了93天
- 如何从void函数输出字符串
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- AES加密到解密未正确输出
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- C++格式化输出问题
- 将值从二维数组输出到文本文件
- 集合上的输出迭代器:assign和increment迭代器
- 我写了一个C++程序来模拟Enigma机器.我没有得到输出
- 我的程序在不同的机器上给出不同的输出
- 不同的机器输出不同的Valgrind