繁体   English   中英

预处理程序定义在“发布”模式下起作用,而不在“调试”下起作用

[英]Preprocessor definitions work in Release mode, not Debug

我试图在一个源文件hw_model.cpp中定义一个预处理器宏,而在另一个main.cpp中将其保留为未定义。

当我在x64发布模式(Visual Studio 2017)中运行该程序时,一切都很好。 当我在x64调试模式下运行时,main.cpp中的#undef ACT_LIKE_HARDWARE语句似乎被忽略。

model.h:

extern Signal signal;
void setSignalsFromHw();


// code below is inside some function :
#ifdef ACT_LIKE_HARDWARE
    // perform a procedure that behaves like hardware
    // This C code is supposed to act like hardware
    // hardware has the freedom to write to read-only variables
#else
    // perform some other procedure that firmware can normally do
#endif

main.cpp中:

#undef ACT_LIKE_HARDWARE

#include "model.h" 

Signals signal;

int main(){
    uint32_t read_data = signal.wv0;
    // do some processing on the read_data

    setSignalsFromHw();
}

hw_model.cpp:

#define ACT_LIKE_HARDWARE

#include "macro.h"

// Perform a cast on the "signal" global variable
// This cast operation is done so that "signal_HWModel" has the freedom to write to read-only fields
Signals_HWModel* signal_HWModel = reinterpret_cast<Signals*>(&signal);

void setSignalsFromHw(){
    ntfySignal_HWModel->wv0 = 0x2;
    ntfySignal_HWModel->wv1 = 0x4;
}

首先,我应该在某些源文件中定义预处理器宏,而在其他源文件中取消定义它吗? 如果没有,什么是一个好的解决方法? 请考虑以下事实:model.h比我提出的要复杂得多,并且重构起来有些困难,但是我绝对愿意接受所有建议。

其次,为什么在调试模式与发布模式之间进行区分?

谢谢

-------------- **更新** --------------

根据要求,这是最小的可运行代码。 它说明了我上面遇到的相同问题。 很抱歉,如果它看起来与上面的略有不同。 我只是注意不要透露太多IP。

重要提示:我正在使用Google Test Framework及其提供的main()函数。 在Release中,我得到了预期的行为(undef语句起作用,并且define语句起作用)。 在调试中,预处理器语句之一不会被命中。

TEST.CPP

#undef ACT_LIKE_HW

#include "gtest/gtest.h"
#include "model.h"

TEST(TestCaseName, TestName) {
    setSignalsFromHW();
    Block::assignSig();
}

hw_model.cpp

#define ACT_LIKE_HW
#include "model.h"

void setSignalsFromHW() {
    Block::assignSig();
}

model.h

#pragma once

#include <iostream>
using namespace std;

void setSignalsFromHW();

class Block {
    public:
        static void assignSig() {
        #ifdef ACT_LIKE_HW
            cout << "Performing hardware operations" << endl;
        #else
            cout << "Procedures that firmware usually executes" << endl;
        #endif
        }
};

但是,如果我创建一个全新的C ++项目(不使用Google Test,因此它是常规的Console应用程序),则其中一个预处理程序语句不会同时被Release和Debug选中,因此这违背了我定义的目的那两个预处理器语句。 我可能最终只是重构代码,但是我仍然想知道为什么我的Google测试项目会发生此问题。

您违反了一个定义规则。

如果程序中有相同符号的多个定义,则如果两个定义都不相同,则程序将具有未定义的行为。

通常,链接器会删除重复的符号,因此只有一个功能可以保留,并且两个调用站点最终都将调用同一功能。

如果该函数是由编译器内联的,则该函数中的代码将集成到调用函数中,并且链接程序不会干涉,因此您的代码可能会正常工作。 这是脆弱的,尽管在调试中没有发生内联时,或者当您的函数超出了对其进行内联的编译器大小阈值时,您将回到只具有单个函数的状态。

要解决此问题,请将布尔参数传递给控制所需行为的函数。 如果内联此函数,则编译器应删除未使用的代码分支。

或者将boolean参数if constexpr模板参数,并使用if constexpr ,这将保证删除未使用的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM