Co to znaczy "zatruć funkcję" w C++?

Na samym końcu rozmowy Scotta Schurra"Introducing constexpr" Na CppCon , pyta "czy istnieje sposób na zatrucie funkcji"? Następnie wyjaśnia, że można to zrobić (choć w niestandardowy sposób) przez: {]}

  1. umieszczanie throw w funkcji constexpr
  2. Ogłoszenie nierozwiązane extern const char*
  3. odwołując się do nierozwiązanych extern w throw

Czuję, że jestem trochę poza moją głębią, ale jestem ciekawa:

  • Co to znaczy " zatruć a funkcja"?
  • jakie jest znaczenie / przydatność techniki, którą opisuje?
Author: Peter Mortensen, 2015-11-27

2 answers

Ogólnie odnosi się to do uczynienia funkcji bezużyteczną, np. jeśli chcesz zakazać używania dynamicznej alokacji w programie, możesz "zatruć" funkcję malloc, aby nie mogła być użyta.

W filmie używa go w bardziej konkretny sposób, co jest jasne, jeśli czytasz slajd, który jest wyświetlany, gdy mówi o zatruciu funkcji, która mówi "sposób na wymuszenie tylko czasu kompilacji?"

Więc mówi o "zatruciu" funkcji, aby była nie do przerobienia w czasie wykonywania, Więc to tylko można wywołać w wyrażeniach stałych. Technika polega na tym, aby mieć gałąź w funkcji, która nigdy nie jest pobierana podczas wywoływania w kontekście czasu kompilacji i aby gałąź ta zawierała coś, co spowoduje błąd.

Wyrażenie throw jest dozwolone w funkcji constexpr, o ile nigdy nie zostanie osiągnięte podczas wywoływania funkcji w czasie kompilacji (ponieważ nie można wyrzucić wyjątku w czasie kompilacji, jest to operacja z natury dynamiczna, jak alokacja pamięci). So a wyrażenie throw, które odnosi się do niezdefiniowanego symbolu, nie będzie używane podczas wywoływania w czasie kompilacji (ponieważ nie powiodłoby się kompilacji) i nie może być użyte w czasie wykonywania, ponieważ niezdefiniowany symbol powoduje błąd linkera.

Ponieważ niezdefiniowany symbol nie jest "używany odr" w wywołaniach funkcji w czasie kompilacji, w praktyce kompilator nie utworzy odniesienia do symbolu, więc jest OK, że jest niezdefiniowany.

Czy to jest przydatne? Demonstruje Jak to zrobić, niekoniecznie mówiąc, że jest to dobry pomysł lub szeroko przydatny. Jeśli musisz to zrobić z jakiegoś powodu, jego technika może rozwiązać twój problem. Jeśli tego nie potrzebujesz, nie musisz się o to martwić.

Jednym z powodów, dla których może być przydatna jest sytuacja, gdy skompilowana wersja jakiejś operacji nie jest tak wydajna, jak mogłaby być. Istnieją ograniczenia dotyczące rodzaju wyrażeń dozwolonych w funkcji constexpr (szczególnie w C++11, niektóre ograniczenia zostały usunięte w C++14). Możesz więc mieć dwie wersje funkcji do wykonywania obliczeń, jedną optymalną, ale używającą wyrażeń, które nie są dozwolone w funkcji constexpr, i drugą, która jest poprawną funkcją constexpr, ale wykonywałaby się źle, gdyby została wywołana w czasie wykonywania. Możesz zatruć nieoptymalną wersję, aby upewnić się, że nigdy nie jest używana do wywołań run-time, upewniając się, że bardziej wydajna (non-constexpr) wersja jest używana do wywołań run-time.

Uwaga: wydajność funkcji constexpr używanej w czasie kompilacji wynosi nie bardzo ważne, ponieważ i tak nie ma nadmiarowego czasu pracy. Może to spowolnić kompilację, zmuszając kompilator do dodatkowej pracy, ale nie będzie kosztować wydajności w czasie wykonywania.

 103
Author: Jonathan Wakely,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-27 21:09:58

'otrucie' identyfikator oznacza, że każde odniesienie do identyfikatora po 'otruciu' jest twardym błędem kompilatora. Technika ta może być użyta na przykład do hard deprecation (funkcja jest przestarzała, nigdy jej nie używaj!).

W GCC tradycyjnie istniała pragma dla tego: #pragma GCC poison.

 17
Author: SergeyA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-27 20:52:01