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
相关产品推荐
相关产品推荐

