Home > Mobile >  Explicit instantiation unexpected behavior - breaking ODR does not cause compilation errors
Explicit instantiation unexpected behavior - breaking ODR does not cause compilation errors

Time:08-11

Let's consider the following code:

output_data.hpp

#pragma once

#include <functional>
#include <cstddef>

namespace example {
    
using Callback = std::function<void(int)>;
struct OutputData {

    void * data = nullptr;
    std::size_t size = 5;
    Callback callback = nullptr;
};

}  // namespace example

buffer.hpp

#pragma once
#include <vector>

namespace example {

template <typename T>
struct Buffer {
    Buffer(std::size_t size);

    std::vector<T> buffer_;
};

} // namespace example

buffer.cpp

#include "buffer.hpp"
#include "output_data.hpp"

namespace example {

template <typename T>
Buffer<T>::Buffer(std::size_t size) : buffer_(size) 
{
}

template struct Buffer<OutputData>;

} // namespace example

main.cpp

#include <iostream>
#include <memory>
#include <functional>
#include "buffer.hpp"

namespace example {

using Callback = std::function<void(int)>;

struct OutputData {
    Callback callback = nullptr;
};

}

int main() {
    std::shared_ptr<int> ptr = std::make_shared<int>(5);

    example::Buffer<example::OutputData> buf(3);

    example::Callback simple_callback = [=](int a) {
        std::cout << a << *ptr << "\n";
    };

    buf.buffer_[1].callback = simple_callback;
}

[Godbolt][https://godbolt.org/z/EEzE7oerb]

The compilation ends without errors, while the execution ends with Segmentation Fault. Segfault is caused by the fact that in main.cpp I used a different struct than the one in buffer.cpp during explicit instantiation. Why was the code compiled without errors? Is it possible to detect such programming mistakes during compilation? Is there any warning flag for detecting such cases ?

CodePudding user response:

Why was the code compiled without errors?

Credit to Richard Critten's comment for the source.

"The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined"

Is it possible to detect such programming mistakes during compilation?

Yes, see below.

Is there any warning flag for detecting such cases ?

Your ODR violation does not exist during compilation of any single source file. It only exists during (after) linking.

g will, unless disabled, warn of ODR violations during link time if Link Time Optimization is enabled with the flag -flto

[Godbolt]

  • Related