在 Windows 中编译的 C++ 程序产生不同的输出

     2023-02-21     41

关键词:

【中文标题】在 Windows 中编译的 C++ 程序产生不同的输出【英文标题】:C++ program compiled in windows produces different output 【发布时间】:2015-07-13 16:50:46 【问题描述】:

我正在解决一个涉及递增计数器并显示它的问题。我初始化和增加变量的方式似乎很正常。见 counter 变量

#include <iostream>
#include <cstring>

using namespace std;

int main()

    char s[5];
    int counter = 1;

    while (cin >> s && (strcmp(s, "*") != 0))
    
        cout << "Case " << counter++ << ": Hajj-e-A";

        if (s[0] == 'H')
        
            cout << "kbar\n";
        
        else if (s[0] == 'U')
        
            cout << "sghar\n";
         
    

但程序神秘地显示了错误的结果。它没有正确地增加从 1 开始的值。查看输出。

Case 1: Hajj-e-Akbar
Case 0: Hajj-e-Asghar
Case 1: Hajj-e-Akbar
Case 0: Hajj-e-Asghar

但是当我尝试通过使用 Linux 的http://www.tutorialspoint.com/compile_cpp_online.php 编译和运行它时,它产生了正确的结果。节目也被在线评委录取。

Case 1: Hajj-e-Akbar
Case 2: Hajj-e-Asghar
Case 3: Hajj-e-Akbar
Case 4: Hajj-e-Asghar

谁能指出这背后的奥秘?为什么 Windows 编译的代码会产生奇怪的结果?非常感谢!

【问题讨论】:

你读入s数组的字符串有多长?任何超过 4 个字符(加上 NUL 终止符)的内容都会溢出数组并丢弃以下内存,可能包括您的 counter 变量。 【参考方案1】:

这是缓冲区溢出。最有可能的是,当您在 Windows 上编译时,counter 变量紧跟在内存中的 s[5] 变量之后,如下所示:

+----+----+----+----+----+----+----+----+----+
| ?? | ?? | ?? | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
 \________ s[5] ________/ \____ counter ____/

由于 Windows 是 little-endian,它存储为 01 00 00 00 而不是您可能期望的 00 00 00 01?? 只是表示我们还不知道那里有什么——它可能是任何东西。

现在,假设您输入“Hardy”并按 Enter。在 ASCII 中,它转换为字节序列 48 61 72 64 79 0D 0A(最后两个是行尾,在 UNIX 上,0D 将被省略)。这就是cin &gt;&gt; s 对内存的作用:

1. Read in 'H':
+----+----+----+----+----+----+----+----+----+
| 48 | ?? | ?? | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
2. Read in 'a':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | ?? | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
3. Read in 'r':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | 72 | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
4. Read in 'd':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | 72 | 64 | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
5. Read in 'y':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | 72 | 64 | 79 | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
6. Read in '\r\n' (or on UNIX, just '\n'), but this isn't put into the memory.
Instead, cin realizes that it has finished reading, and closes off the string with a '\0':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | 72 | 64 | 79 | 00 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
 \________ s[5] ________/ \____ counter ____/

哎呀!它覆盖了计数器!

为什么它可以在 Linux 上正常工作?要么 Linux 没有将这两个变量相邻放置在内存中,要么 Linux 系统是大端的,这意味着内存的布局是这样的:

+----+----+----+----+----+----+----+----+----+
| ?? | ?? | ?? | ?? | ?? | 00 | 00 | 00 | 01 |
+----+----+----+----+----+----+----+----+----+

因此,即使您读入 5 个字符,最终的空终止符也只会替换已经存在的 0。当然,如果是这个原因,那么读入 6 个字符就真的很麻烦了。

你如何解决它?问题是,要保存长度为n 的字符串,字符数组的长度必须为n+1。所以你可以这样做:

char s[6];

或者更好的是,使用字符串:

std::string s;

(为此您需要#include &lt;string&gt;。)

【讨论】:

很好地使用了 ASCII 艺术。 :-)

有没有办法在 C++ 编译时限制数据大小并产生编译错误?

】有没有办法在C++编译时限制数据大小并产生编译错误?【英文标题】:IsthereawaytolimitdatasizeatC++compiletimeandproduceacompileerror?【发布时间】:2019-03-3010:12:06【问题描述】:我已经构建了一个工具,使学生能够在线(在受保护的环境... 查看详情

如何在 Windows 命令提示符下使用 Dev C++ 编译器编译 C++ 程序?

】如何在Windows命令提示符下使用DevC++编译器编译C++程序?【英文标题】:Howtocompileac++programusingDevC++compilerinwindowscommandprompt?【发布时间】:2019-02-1115:40:23【问题描述】:我在Windows中安装了DevC++并使用该IDE,但是我想在Windows命令... 查看详情

是啥导致在单元测试(NUnit 或 MSTest)中从 C# 调用的 C++ 函数与在控制台应用程序中运行的相同代码产生不同的结果?

...测试(NUnit或MSTest)中从C#调用的C++函数与在控制台应用程序中运行的相同代码产生不同的结果?【英文标题】:WhatiscausingaC++functioncalledfromC#inaunittest(NUnitorMSTest)toproduceadifferentresultfromthesamecoderuninaconsoleapp?是什么导致在单元测试... 查看详情

在 Windows 7 中交叉编译 C 和 C++ 应用程序,在 linux 下使用 MinGW

】在Windows7中交叉编译C和C++应用程序,在linux下使用MinGW【英文标题】:Cross-CompilingCandC++applicationinWindows7,usingMinGWunderlinux【发布时间】:2011-09-1608:36:06【问题描述】:我在Windows7中安装了MinGW编译器。GCC版本是4.6.1。我有HelloWorld应... 查看详情

在 Windows 上使用 Emacs 编译 C++ 程序

】在Windows上使用Emacs编译C++程序【英文标题】:CompilingC++ProgramswithEmacsonWindows【发布时间】:2009-04-1121:47:16【问题描述】:我已经使用Emacs进行基本的文本编辑已经有一段时间了,但到今天为止,我正尝试将它用于c++编译。在过... 查看详情

c++产生不同随机数

...RAND_MAX的大小可以查看,在include文件夹(linux在usr目录、windows在安装目录)的stdlib.h可以看到,linux下其值为2147483647(),其值与具体系统有关。范例:二.指定范围产生随机数,产生0到某个数的随机数没有现成的函数,但是可... 查看详情

C++:在多个线程中访问同一数组/向量的不同单元是不是会产生数据竞争?

...++:在多个线程中访问同一数组/向量的不同单元是不是会产生数据竞争?【英文标题】:C++:Doesaccessingdifferentcellsofthesamearray/vectorinmultiplethreadscreateadatarace?C++:在多个线程中访问同一数组/向量的不同单元是否会产生数据竞争?【... 查看详情

使用 Eclipse 在 Windows 中为 Linux 编译 C++ 程序?

】使用Eclipse在Windows中为Linux编译C++程序?【英文标题】:CompilingC++programforLinuxinWindowsusingEclipse?【发布时间】:2010-07-2914:45:16【问题描述】:我想知道是否可以使用Eclipse在Windows中为Linux编写和调试C++应用程序?如果是这样,您能... 查看详情

如何使用 LLVM 在 Windows 上为 ARM 编译 C++ 程序?

】如何使用LLVM在Windows上为ARM编译C++程序?【英文标题】:HowtocompileC++programonWindowsforARMusingLLVM?【发布时间】:2018-11-2814:00:35【问题描述】:目标仅使用LLVM在Windows上为ARM编译C++程序。为什么LLVM因为许可许可。我开始怀疑我对LLVM... 查看详情

在 Windows 的 Eclipse C++ 中运行 Hello World 应用程序

】在Windows的EclipseC++中运行HelloWorld应用程序【英文标题】:RunningaHelloWorldapplicationinEclipseC++inWindows【发布时间】:2012-02-2617:19:48【问题描述】:我刚刚下载并投入运行EclipseC++、Windows以及MinGW(我已将其bin/目录设置在PATH变量中)... 查看详情

在 C++ 中为 Windows CE 在 Linux 中开发

】在C++中为WindowsCE在Linux中开发【英文标题】:DevelopInC++ForWindowsCEInLinux【发布时间】:2009-07-1500:34:19【问题描述】:我如何在我的LinuxUbuntu中为我的Jornada720开发和编译命令行C++程序,它有一个WindowsCE3.1(HPC2000),类似于Palm的编译... 查看详情

Windows 驱动程序中的 C++ [关闭]

】Windows驱动程序中的C++[关闭]【英文标题】:C++inaWindowsDriver[closed]【发布时间】:2014-08-1210:29:55【问题描述】:我正在编写一个简单的WDM驱动程序,我想在其中使用一个C++类。我的问题是我不确定应该将编译后的文件链接到哪个... 查看详情

C++ 程序在 VC++ 2010 中编译,但在 Visual C++ 6.0 中没有

...就在那里!VS2010中包含的文件#include<cstdlib>#include<windows.h& 查看详情

c++中#if#ifdef的作用

用编译器经常会自动生成这些,我自己很少用,想知道经常用的这些的介绍,谢谢了。谢谢大家的回答有没有那本书里面有比较详细一点的介绍类似的这些作用,或者给个超链接一般情况下,源程序中所有的行都参加编译。但是... 查看详情

c++中啥是多态!

...的,而不是面向对象的。c++中的多态性具体体现在运行和编译两个方面。运行时多态是动态多态,其具体引用的对象在运行时才能确定。编译时多态是静态多态,在编译时就可以确定对象使用的形式。c++中,实现多态有以下方法... 查看详情

求助:为啥我编的c++程序在自己电脑上能正常运行,但编译后挂在后台linux系统下就总是运行一半后出错,

...;首先你自己电脑上编程是什么环境呢,是linux吗,还是windows;如果是windows的话,windows下的编程放到linux下跑,本身就有可能出现问题的。有些系统库是不同的。 参考技术B重新用gcc编译一次,再运行,这是段错误啊,可能是因... 查看详情

如何在 Cython 中使用不同的 C++ 编译器?

】如何在Cython中使用不同的C++编译器?【英文标题】:HowtouseadifferentC++compilerinCython?【发布时间】:2019-12-0200:20:45【问题描述】:我正在开发一个从Python调用C++的项目。我们为此目的使用Cython。使用命令“python3.6setup.pybuild_ext--inp... 查看详情

如何隐藏在 Qt 应用程序中打开的 Windows 终端?

】如何隐藏在Qt应用程序中打开的Windows终端?【英文标题】:HowtohidewindowsTerminalopenedinQtapp?【发布时间】:2019-05-0810:27:09【问题描述】:首先,有类似的问题,但我认为这是一个不同的问题,因为Windows终端仅在我调用system()时出... 查看详情