【问题标题】:Benchmarking - g++ produces different code from MSVC基准测试 - g++ 生成与 MSVC 不同的代码
【发布时间】:2021-11-17 15:32:56
【问题描述】:

我正在编写一个基准测试,用于测量我的程序的速度和内存使用情况。我在 VS19 工作,但我的测试将在 linux 机器上运行,所以我需要在 g++ 中编译它。我的问题是,在 VS19 中,我的代码产生了我期望的正确结果,用 g++ 编译却产生了错误的结果。

问题在于内存测量。在 Functions.cpp 中,我重载了 new 和 delete

AllocationMetrics s_allocationMetrics;

void* operator new(size_t size) {
    //cout << "Allocate " << size << " bytes\n";
    s_allocationMetrics.totalMemory += size;
    return malloc(size);
}

void operator delete(void* ptr, size_t size) {
    //cout << "Deallocate " << size << " bytes\n";
    s_allocationMetrics.totalFree += size;
    free(ptr);
}

在 Functions.h 中,我创建了这个结构,用于跟踪内存分配

struct AllocationMetrics {
    uint64_t totalMemory = 0;
    uint64_t totalFree = 0;
    uint64_t getCurrentUsage() { return totalMemory - totalFree; }
    uint64_t maxMem=0;
    void setMaxMem() {
        uint64_t temp= getCurrentUsage();
        if (temp > maxMem)
            maxMem = temp;
    }
    void resetMaxMem() { maxMem = 0; }
};

在我需要测量的 Functions.cpp 的 in 函数中,我调用 setMaxMem 并在我的 Benchmark.cpp 中调用 resetMaxMem,如果合适的话。该结构在 Functionc.cpp 中声明,在所有其他 .cpp 文件中它被声明为 extern。

对于这个例子,我在循环中运行我的基准测试 6x,并使用 Visual Studio 的 MSVC,我得到了预期的内存结果,以及所有可能的设置(调试、发布等)。

Params:                 1063 x 24       5       5       255
        Sorting                 0.0084792s              0.36439MB
        Stripes                 0.0179886s              1.64792MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.0080979s              0.364406MB
        Stripes                 0.0165975s              1.64794MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.0080586s              0.364422MB
        Stripes                 0.0163024s              1.64795MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.0081503s              0.364438MB
        Stripes                 0.016274s               1.64797MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.0079747s              0.364454MB
        Stripes                 0.0170647s              1.64799MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.0079046s              0.364486MB
        Stripes                 0.0160469s              1.64801MB

当我用 g++ 编译器 g++ Source.cpp Functionc.cpp benchmarking.cpp 编译相同的代码时,我得到了这些错误的结果

Params:                 1063 x 24       5       5       255
        Sorting                 0.063828s               1.0806MB
        Stripes                 0.171574s               3.73044MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.061869s               4.32227MB
        Stripes                 0.172318s               6.97212MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.067859s               7.56395MB
        Stripes                 0.170573s               10.2138MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.063863s               10.8057MB
        Stripes                 0.171541s               13.4555MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.062963s               14.0473MB
        Stripes                 0.170528s               16.6972MB

Params:                 1063 x 24       5       5       255
        Sorting                 0.064827s               17.2891MB
        Stripes                 0.171541s               19.9389MB

在 g++ 编译中其他一切都是正确的,我尝试了不同的优化级别,这个内存错误没有改变。我使用 g++ (MinGW.org GCC-6.3.0-1) 6.3.0 版本。我也试过用clang运行它,但出现了同样的错误。

看起来好像 delete 重载没有对 g++ 生效,或者释放变量时没有调用 delete。 我尝试在 Windows 和 Linux(相同版本的 g++)上编译,这个 bug 出现在两个版本中。

EDIT1:忘记了一行带有temp定义的代码。

【问题讨论】:

  • 来自operator_delete(5,6),"除了在删除不完整类型的对象和非-class 和可简单破坏的类类型。”。是你的情况吗?
  • 可能不相关:AllocationMetrics s_allocationMetrics; 不应该是 extern AllocationMetrics s_allocationMetrics; 吗?另外,temp 是在哪里定义的?
  • @TedLyngmo 忘记了这条线,它在 setMaxMem() 中,现在添加到帖子中。 s_allocationMetrics 在所有其他文件(Source.cpp、benchmarking.cpp)中是外部的,但在 Functions.cpp 中不是外部的
  • @AleksanderMarkovskyy 好的,s_allocationMetrics?为什么不是extern?
  • @Jarod42 我不太明白,什么是不完整类型?我主要处理浮点和短向量。在 g++ 中,运算符 delete 不会被调用一次,而在 MSVC 中,它似乎在每次变量超出范围时都会被调用。

标签: c++ memory visual-c++ g++


【解决方案1】:

感谢 Jarod42 提供有用的 cmets。

问题在于 GCC 6.3.0 选择了不同的删除重载,即 delete(void*) 而不是我所针对的 delete(void*, size_t size)。 为了让 GCC 正常运行,我将其升级到更新的 11.2.0 版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 2012-01-15
    • 2013-04-16
    • 2023-02-19
    相关资源
    最近更新 更多