2

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.

Abdul ahad
  • 1,383
  • 7
  • 18
  • Have you tried using this `std::map> rtc::stream_buffer::buffer{{1, {1, 2, 3, 4}}};? May be it is due to initialization of std::map. ` – Muhammad Usman Bashir Dec 07 '20 at 16:14
  • Does this answer your question? [How to deal with "exit-time destructor" warning in clang?](https://stackoverflow.com/questions/14335494/how-to-deal-with-exit-time-destructor-warning-in-clang) – Daniel Langr Dec 07 '20 at 16:14
  • @MuhammadUsman Yes sir, I have tried. It is not the issue of initialization of map. – Abdul ahad Dec 07 '20 at 16:15
  • @DanielLangr, Sir I have visited this issue multiple times, but its not helping me out. Can you please suggest me some other solution. I have already done a couple searches on google from last week. – Abdul ahad Dec 07 '20 at 16:18
  • Can you intentionally leak the map rather than have it destructed at program termination? Can you make it so the map is constructed on first access (using an instance getter helper function), rather than being constructed at some time before `main` is invoked? – Eljay Dec 07 '20 at 16:19
  • It's only a warning, which would not hinder compilation if `-Werror` was not used. Are you sure it causes any real problems? – Daniel Langr Dec 07 '20 at 16:22
  • @Abdulahad If I am not wrong, WebRtc is using these flags to deal with trivial and non trivial destructible objects. As based on this google guide `Objects with static storage duration are forbidden unless they are trivially destructible`. @Ejiay, @DanielLangr You can also visit this link [Static and Global Variables](https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables). – Muhammad Usman Bashir Dec 07 '20 at 16:23
  • @DanielLangr I know that solution, If I simply remove these flags `-Wglobal-constructors, -Wexit-time-destructors, -Werror`, but I don't want to remove these flags because when I would compile the library on production time, these flags would help us in future developments. Please provide me any other solution. – Abdul ahad Dec 07 '20 at 16:29
  • @Abdulahad Then, I guess, you create the map dynamically. Something as simplified: https://godbolt.org/z/eTjcjv. The static variable is only a pointer, which does not cause any troubles. However, note that you need to `delete` that pointer somewhere manually, since it won't be done automatically. Some scope guard in `main` may help. – Daniel Langr Dec 07 '20 at 16:37
  • @DanielLangr thank you, sir. It worked like a marvel. It's my first question on StackOverflow. You helped me a lot. If possible, then could you please provide me your email address? – Abdul ahad Dec 07 '20 at 16:47
  • @Abdulahad I really don't want to public my e-mail address here. May I ask you why do you need it? (BTW, I didn't posted an answer since it is basically here: https://stackoverflow.com/a/19803514/580083.) – Daniel Langr Dec 08 '20 at 07:00
  • @DanielLangr can you please add your solution as a answer. It worked for me. – Abdul ahad Dec 08 '20 at 12:38

1 Answers1

2

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.

Daniel Langr
  • 22,196
  • 3
  • 50
  • 93