You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Visual Studio编译成功但未生成.exe文件问题求助

Qt遥测项目构建成功但找不到.exe文件的排查方案

项目背景

我正在为大学项目开发一款遥测软件,此前更熟悉Python,刚接触C++。参考教程并借助GPT-3编写了基于Qt的代码,在Visual Studio中构建时输出显示成功,但调试时找不到生成的.exe文件,项目目录中也无该文件。测试简单HelloWorld项目可正常生成并运行.exe,排除环境整体问题。

项目代码

// 定义_USE_MATH_DEFINES以使用M_PI
#define _USE_MATH_DEFINES

// 导入库
#include "telemetry.h"
#include <QApplication>
#include <QMainWindow>
#include <QTabWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QStandardItemModel>
#include <QTableView>
#include <QCustomPlot>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QImage>
#include <QLabel>
#include <QGraphicsScene>
#include <QGraphicsEllipseItem>
#include <QGraphicsView>
#include <QPainter>
#include <QThread>
#include <cmath>

// 存储遥测数据的结构
struct TelemetryData {
    double time;
    double distance;
    double speed;
    double acceleration;
    double acceleratorPressure;
    double brakePressure;
    double gpsPositionX;
    double gpsPositionY;
};

//----------------------------------------------------------------------------- 主函数 ------------------------------------------------------------------------------

int main(int argc, char* argv[])
{
    // ---------- 创建各种显示组件、按钮和标签页 --------
    QApplication app(argc, argv);

    // 创建应用主窗口
    QMainWindow window;
    window.setWindowTitle("Télémétrie");

    // 创建窗口主布局
    QWidget* centralWidget = new QWidget(&window);
    QVBoxLayout* mainLayout = new QVBoxLayout(centralWidget);
    window.setCentralWidget(centralWidget);

    // 创建QTabWidget并添加到界面
    QTabWidget* tabWidget = new QTabWidget(centralWidget);
    mainLayout->addWidget(tabWidget);

    // 创建第一个标签页:显示油门和刹车压力图表
    QWidget* firstTab = new QWidget();
    QVBoxLayout* firstTabLayout = new QVBoxLayout(firstTab);

    // 创建油门和刹车压力图表
    QCustomPlot* pressureGraph = new QCustomPlot(firstTab);
    pressureGraph->addGraph();
    pressureGraph->addGraph();
    pressureGraph->graph(0)->setPen(QPen(Qt::green));
    pressureGraph->graph(1)->setPen(QPen(Qt::red));
    pressureGraph->xAxis->setLabel("Temps (ms)");
    pressureGraph->yAxis->setLabel("Pression (bars)");
    pressureGraph->yAxis->setRange(0, 1);
    firstTabLayout->addWidget(pressureGraph);

    // 创建图表控制按钮
    QPushButton* pauseButton = new QPushButton("Mettre en pause", firstTab);
    QPushButton* nextButton = new QPushButton("Milliseconde suivante", firstTab);
    QPushButton* previousButton = new QPushButton("Milliseconde précédente", firstTab);
    QPushButton* forwardButton = new QPushButton("Avancer x3", firstTab);
    QPushButton* backwardButton = new QPushButton("Reculer x3", firstTab);
    firstTabLayout->addWidget(pauseButton);
    firstTabLayout->addWidget(nextButton);
    firstTabLayout->addWidget(previousButton);
    firstTabLayout->addWidget(forwardButton);
    firstTabLayout->addWidget(backwardButton);

    // 将标签页添加到QTabWidget
    tabWidget->addTab(firstTab, "Graphique de pression d'accélérateur et de frein");

    // 创建第二个标签页:显示遥测数据表格
    QWidget* secondTab = new QWidget();
    QVBoxLayout* secondTabLayout = new QVBoxLayout(secondTab);

    // 创建数据模型和表格
    QStandardItemModel* model = new QStandardItemModel(0, 8, secondTab);
    model->setHeaderData(0, Qt::Horizontal, "Temps (ms)");
    model->setHeaderData(1, Qt::Horizontal, "Distance (m)");
    model->setHeaderData(2, Qt::Horizontal, "Vitesse (m/s)");
    model->setHeaderData(3, Qt::Horizontal, "Accélération (m/s^2)");
    model->setHeaderData(4, Qt::Horizontal, "Pression d'accélérateur (bars)");
    model->setHeaderData(5, Qt::Horizontal, "Pression de frein (bars)");
    model->setHeaderData(6, Qt::Horizontal, "Position GPS X (m)");
    model->setHeaderData(7, Qt::Horizontal, "Position GPS Y (m)");

    // 创建表格视图
    QTableView* tableView = new QTableView(secondTab);
    tableView->setModel(model);
    secondTabLayout->addWidget(tableView);

    // 将标签页添加到QTabWidget
    tabWidget->addTab(secondTab, "Données de télémétrie");

    // 创建切换标签页按钮
    QPushButton* switchTabButton = new QPushButton("Changer d'onglet", centralWidget);
    mainLayout->addWidget(switchTabButton);

    // 连接按钮点击信号到切换标签页的槽函数
    QObject::connect(switchTabButton, &QPushButton::clicked, [&tabWidget]() {
        int currentIndex = tabWidget->currentIndex();
        int newIndex = (currentIndex + 1) % tabWidget->count();
        tabWidget->setCurrentIndex(newIndex);
        });

    // --------------------- 打开文件 -------------------
    // 打开遥测数据文件读取
    QFile file("telemetry.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        // 文件无法打开时显示错误
        QMessageBox::critical(nullptr, "Erreur", "Impossible d'ouvrir le fichier de données de télémétrie");
        return -1;
    }

    // 从文件收集遥测数据
    QTextStream in(&file);
    QVector<TelemetryData> data;
    while (!in.atEnd()) {
        QString line = in.readLine();
        QStringList fields = line.split("\t");
        if (fields.size() != 8) {
            // 数据格式错误时显示错误
            QMessageBox::critical(nullptr, "Erreur", "Format de données de télémétrie incorrect");
            return -1;
        }

        TelemetryData datum;
        datum.time = fields[0].toDouble();
        datum.distance = fields[1].toDouble();
        datum.speed = fields[2].toDouble();
        datum.acceleration = fields[3].toDouble();
        datum.acceleratorPressure = fields[4].toDouble();
        datum.brakePressure = fields[5].toDouble();
        datum.gpsPositionX = fields[6].toDouble();
        datum.gpsPositionY = fields[7].toDouble();
        data.append(datum);
    }
    file.close();

    // -------------- 优化显示组件 --------------
    // 创建gnuplot对象绘制速度仪表盘(注意:需确保项目已链接gnuplot相关库)
    Gnuplot gp;
    gp << "set terminal qt size 350,200 font ',14'\n";
    gp << "set style data line\n";
    gp << "set xrange [-1:1]\n";
    gp << "set yrange [-1:1]\n";
    gp << "set border 0\n";
    gp << "set tics out\n";
    gp << "set nokey\n";
    gp << "unset colorbox\n";
    gp << "set object 1 circle at 0,0 size 1.1 fc rgb 'white'\n";
    gp << "set object 2 circle at 0,0 size 1 fc rgb 'black'\n";
    gp << "set object 3 circle at 0,0 size 0.9 fc rgb 'red'\n";
    gp << "set object 4 circle at 0,0 size 0.1 fc rgb 'black'\n";
    gp << "set object 5 circle at 0,0 size 0.07 fc rgb 'white'\n";

    // 创建赛道俯视图
    QImage circuitImage("circuit.png");
    QLabel* circuitLabel = new QLabel(centralWidget);
    circuitLabel->setPixmap(QPixmap::fromImage(circuitImage));
    circuitLabel->setScaledContents(true);
    circuitLabel->setFixedSize(500, 500);
    mainLayout->addWidget(circuitLabel);

    // 在赛道图上绘制红色小车位置
    QGraphicsScene* circuitScene = new QGraphicsScene(circuitLabel);
    QGraphicsEllipseItem* car = new QGraphicsEllipseItem(0, 0, 10, 10);
    car->setBrush(QBrush(Qt::red));
    circuitScene->addItem(car);
    QGraphicsView* circuitView = new QGraphicsView(circuitScene, circuitLabel);
    circuitView->setRenderHint(QPainter::Antialiasing);
    circuitView->setRenderHint(QPainter::SmoothPixmapTransform);
    circuitView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    circuitView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    circuitView->setFixedSize(500, 500);

    // 创建速度仪表盘
    QLabel* speedGauge = new QLabel(centralWidget);
    speedGauge->setFixedSize(350, 200);
    speedGauge->setPixmap(QPixmap::fromImage(gp.plot(QString(""), "", "", "", false).scaled(350, 200)));
    mainLayout->addWidget(speedGauge);

    // 显示主窗口(修正原代码变量名错误:mainWindow改为window)
    window.show();

    // ---------------- 实时更新功能 ---------------
    // 初始化当前显示的遥测数据索引
    int dataIndex = 0;

    // 初始化实时读取暂停状态
    bool paused = false;

    // 注意:原代码的while(true)会阻塞Qt事件循环,正确做法应使用QTimer,此处保留原结构但标注问题
    while (true) {
        // 更新油门和刹车压力图表
        pressureGraph->graph(0)->addData(data[dataIndex].time, data[dataIndex].acceleratorPressure);
        pressureGraph->graph(1)->addData(data[dataIndex].time, data[dataIndex].brakePressure);
        pressureGraph->xAxis->setRange(data[dataIndex].time, 8, Qt::AlignRight);
        pressureGraph->replot();

        // 更新速度仪表盘
        double speedRatio = data[dataIndex].speed / 140.0;  // 140 km/h为最大速度
        gp << "set object 4 circle at " << QString::number(speedRatio * std::sin(M_PI / 4)).toStdString()
            << "," << QString::number(-speedRatio * std::cos(M_PI / 4)).toStdString()
            << " size 0.1 fc rgb 'black'\n";
        speedGauge->setPixmap(QPixmap::fromImage(gp.plot(QString(""), "", "", "", false).scaled(350, 200)));

        // 更新赛道图上的小车位置
        car->setPos(250 + data[dataIndex].gpsPositionX * 3, 250 - data[dataIndex].gpsPositionY * 3);  // 250,250为图像中心

        // 更新遥测数据表格显示
        // 修正原代码逻辑:原model初始行数为0,需先添加行再设置数据
        if (model->rowCount() < data.size()) {
            for (int i = model->rowCount(); i < data.size(); ++i) {
                model->insertRow(i);
            }
        }
        for (int i = 0; i < data.size(); ++i) {
            model->setData(model->index(i, 0), data[i].time);
            model->setData(model->index(i, 1), data[i].distance);
            model->setData(model->index(i, 2), data[i].speed);
            model->setData(model->index(i, 3), data[i].acceleration);
            model->setData(model->index(i, 4), data[i].acceleratorPressure);
            model->setData(model->index(i, 5), data[i].brakePressure);
            model->setData(model->index(i, 6), data[i].gpsPositionX);
            model->setData(model->index(i, 7), data[i].gpsPositionY);
        }
        tableView->scrollTo(model->index(dataIndex, 0));

        // 等待1毫秒后再次更新
        QThread::msleep(1);

        // 未暂停时切换到下一条数据
        if (!paused) {
            ++dataIndex;
        }
        if (dataIndex >= data.size()) {
            dataIndex = 0;
        }

        // 处理Qt事件,避免界面冻结
        app.processEvents();
    }

    return app.exec();
}

构建输出

Build started...
1>------ Build started: Project: Telemetrie_PITA, Configuration: Debug x64 ------
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

排查与解决方法

1. 定位Visual Studio输出目录

右键项目 → 属性 → 配置属性 → 常规,查看「输出目录」的路径(默认格式为$(SolutionDir)$(Platform)\$(Configuration)\),直接前往该路径查找Telemetrie_PITA.exe。

2. 确认项目类型与链接器设置

  • 右键项目 → 属性 → 配置属性 → 链接器 → 系统,检查「子系统」设置:需为Windows (/SUBSYSTEM:WINDOWS)或Console (/SUBSYSTEM:CONSOLE),若设置为Not Set或库类型,将不会生成exe文件。
  • 确认项目是应用程序项目,而非静态库/动态库项目(库项目生成的是.lib/.dll文件)。

3. 清理并重新构建

菜单栏 → 生成 → 清理解决方案,之后选择重新生成解决方案,清除旧的构建缓存,避免因缓存异常导致exe未生成。

4. 修复代码中的编译错误

原代码存在多个编译级错误,可能导致Visual Studio表面显示构建成功,但实际未生成exe:

  • 缺失必要头文件:添加#include <QCustomPlot>、#include <QMessageBox>、#include <QThread>等,定义#define _USE_MATH_DEFINES以使用M_PI。
  • 变量名错误:原代码最后调用mainWindow.show();,但实际定义的主窗口变量是window,应改为window.show();。
  • 表格数据更新逻辑错误:原model初始行数为0,直接设置数据无效,需先插入对应行数再赋值。
  • 阻塞Qt事件循环:while(true)会导致界面冻结,应替换为QTimer实现实时更新,同时在循环中添加app.processEvents();临时处理事件。

5. 查看详细构建日志

菜单栏 → 视图 → 输出,切换到「生成」输出面板,查看是否有隐藏的警告或错误信息(部分链接错误可能不会触发构建失败提示,但会导致exe无法生成)。

内容的提问来源于stack exchange,提问作者AdrienMrc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:30:44