Search code examples
c++gccclangwebrtc

declaration requires an exit-time destructor [-Werror,-Wexit-time-destructors]


What I am trying is to compile WebRtc Library for android and I am getting this mind blowing error. Please if someone could assist me in this matter. I have these implementations:

stream_buffer.h

#ifndef AUDIO_STREAM_BUFFER_H_
#define AUDIO_STREAM_BUFFER_H_
​
#include <array>
#include <cstdint>
#include <iostream>
#include <list>
#include <map>
#include <utility>
​
// #include "api/scoped_refptr.h"
#include "rtc_base/constructor_magic.h"
#include "rtc_base/ref_count.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/thread_checker.h"
​
namespace rtc {
​
class RTC_EXPORT stream_buffer {
 
 public:
  
  stream_buffer() = delete;
  ~stream_buffer();
​
  static std::map<unsigned char, std::list<unsigned char>> buffer;
  mutable int ref_count_ RTC_GUARDED_BY(buffer) = {};
​
  // typedef unsigned char uint_8;
  typedef unsigned char uint8_t;
​
  static void push(uint8_t ssrc, std::list<uint8_t> value);
​
  static void pop();
​
  static std::list<unsigned char> get_payload(uint8_t ssrc);
​
  static void get_buffer_stats();
​
 private:
​
  RTC_DISALLOW_COPY_AND_ASSIGN(stream_buffer);
};
​
}  // namespace rtc
​
#endif  // AUDIO_STREAM_BUFFER_H_

stream_buffer.cc

#include "stream_buffer.h"
​
namespace rtc {
​
​
 std::map<unsigned char, std::list<unsigned char>> rtc::stream_buffer::buffer = {};
​
void stream_buffer::push(uint8_t ssrc, std::list<uint8_t> buf) {
  std::list<unsigned char> temp = std::move(buf);
​
  if (buffer.find(ssrc) == buffer.end()) {
    buffer.insert(std::pair<uint8_t, std::list<uint8_t>>(ssrc, temp));
  } else {
    buffer.find(ssrc)->second.push_back(temp.front());
    std::cout << "SSRC: " << ssrc
              << " bufferSize: " << buffer.find(ssrc)->second.size() << '\n';
  }
}
​
void stream_buffer::pop() {
  for (auto it = buffer.begin(); it != buffer.end(); ++it) {
    if (!buffer.find(it->first)->second.empty()) {
      std::cout << "key: " << int(it->first) << " pop value: ";
      for (auto v : buffer[int(it->first)]) {
        std::cout << int(v) << ' ';
      }
      std::cout << "\n";
      buffer.find(it->first)->second.pop_front();
    } else {
      std::cout << "Empty buffer for " << it->first << '\n';
    }
  }
}
​
std::list<unsigned char> stream_buffer::get_payload(
    stream_buffer::uint8_t ssrc) {
  if (buffer.find(ssrc) != buffer.end()) {
    return buffer[ssrc];
  } else {
    std::cout << "\nstream_buffer.cpp -> Invalid SSRC.\n";
    return static_cast<std::list<unsigned char>>(0);
  }
}
​
void stream_buffer::get_buffer_stats() {
  std::cout << "\nstream_buffer.cpp -> stream_buffer stats:\n";
  for (auto it = buffer.begin(); it != buffer.end(); ++it) {
    if (buffer.find(it->first) != buffer.end()) {
      std::cout << "SSRC: " << int(it->first)
                << " bufferSize: " << buffer.find(it->first)->second.size()
                << '\n';
    }
  }
}
}

Basically I have declared a static map in one the above class with the name of stream_buffer::buffer. When I try to compile the library, I am getting the following error.

on this line in stream_buffer.cc file.

std::map<unsigned char, std::list<unsigned char>> rtc::stream_buffer::buffer = {};

I have already visited multiple stack overflow issues, but didn't find anything useful.

  1. How to deal with “exit-time destructor” warning in clang?

I would much appreciate being pointed in the right direction on either issue.


Solution

  • You can create your map dynamically. Something as, simplified:

    class X
    {
       static std::map<int, int>* ptr_;        
    
    public:
       static std::map<int, int>& buffer()
       {
          return *ptr_;
       }
     
       static void finalize()
       {
          delete ptr_;
       }
    };
    
    std::map<int, int>* X::ptr = new std::map<int, int>{};        
    

    Now, since the static variable is an ordinary pointer, there is no problem with constructors and destructors.

    Note that you need to delete the map manually, here by calling X::finalize() somewhere at the end of your program.