debugging 调试和发布中的不同行为

pdsfdshx  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(80)

在我的自定义ArrayProxy类中。我有个测试。

"array_proxy_initializer_list"_test = [] {
        ArrayProxy<int> array = { 1, 2, 3, 4, 5 };
        expect(array.size() == 5);
        expect(array[0] == 1);
        expect(array[1] == 2);
        expect(array[2] == 3);
        expect(array[3] == 4);
        expect(array[4] == 5);
        LogInfo{array[0]};// in release log: 1166876000 
        LogInfo{array[1]};// in release log: 32758
    };

处于调试模式。它工作正常。并在释放模式。它失败了。
下面是我的ArrayProxy类。

template<typename T>
    concept ContainerObject = requires(T t) {
        t.data();
        t.size();
    };

    template<typename T>
    class ArrayProxy
    {
    public:
        using value_type = T;

        constexpr ArrayProxy() : m_count(0), m_ptr(nullptr) {}
        constexpr ArrayProxy(std::nullptr_t) : m_count(0), m_ptr(nullptr) {}
        ArrayProxy(const T& value) : m_count(1), m_ptr(&value) {}
        ArrayProxy(std::size_t count, const T* ptr) : m_count(count), m_ptr(ptr) {}
        ArrayProxy(const std::initializer_list<T>& args) : m_count(args.size()), m_ptr(args.begin()) {}
        ArrayProxy(ContainerObject auto container) : m_count(container.size()), m_ptr(container.data()) {}

        template<std::size_t N>
        ArrayProxy(const T (&ptr)[N]) : m_count(N), m_ptr(ptr) {};

        const T& operator[](int i) const
        {
            return m_ptr[i];
        }

        std::size_t size() const
        {
            return m_count;
        }

        const T* data() const
        {
            return m_ptr;
        }

    private:
        const T*    m_ptr;
        std::size_t m_count;
    };

在我的调试中。我发现一个有趣的行为。
如果我交换m_ptr和m_count的顺序。

private:
        std::size_t m_count;
        const T*    m_ptr;
    };

在调试和发布模式下。它工作正常。
我不知道为什么,我的代码里有一个ub吗?
在msvc 2022和c++20上编译。

iugsix8n

iugsix8n1#

谢谢@Peter。我知道如何测试这个类。std::initializer_list的生命期if from函数的调用返回。
这个类用于 Package 一些c API如void c_api(int* data, int size);。使用这个类对现代cpp容器是友好的。
举个例子。

void c_api_wrapped(const ArrayProxy<int>& arr)
{
    c_api(arr.data(), arr.size());
}

void test()
{
    c_api_wrapped(1);
    c_api_wrapped({1,2,3});
    std::vector<int> arr = {1,2,3};
    c_api_wrapped(arr);
}

它是友好的这些临时值调用。
但我的用例是在一个错误的方式。这个类只能在函数的参数中使用。
如果我用它作为一个变量以其他方式。std::initializer_list将被销毁。
所以我应该把我的测试改为:

void test_array_proxy(const rain::ArrayProxy<int>& arr, const std::vector<int>& ground_truth)
{
    boost::ut::expect(arr.size() == ground_truth.size());
    for(int i = 0; i < arr.size(); ++i)
    {
        boost::ut::expect(arr[i] == ground_truth[i]);
    }
}

int main()
{
    "array_proxy_initializer_list"_test = [] {
        std::vector<int> ground_truth = { 1, 2, 3, 4, 5 };
        test_array_proxy({ 1, 2, 3, 4, 5 }, ground_truth);
    };
}

它将工作得很好,并显示了这个类的用法。
正如我提到的,这个类来自vulkan-hpp。vulkan-hpp还提供了“ArrayProxyNoTemporaries”来防止这些情况。
谢谢你的帮助!

相关问题