Last active
December 8, 2018 16:33
-
-
Save geneotech/fa5998de35c0d8b5b234cba8eb8b2659 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
To pokazuje jak se można odstrzelić całą nogę w tym języku. | |
Miałem takiego buga, że jak do jednego pliku, | |
nazwijmy go crash.cpp - nie wrzuciłem jednego includa - to miałem crasha w serializacja.cpp. | |
Co ciekawe, funkcje z crash.cpp w ogóle nie były wykorzystywane podczas testowania. | |
Więc mam se w kodzie takie generalne templatki do serializacji, write_bytes oraz read_bytes, | |
które z dowolnego obiektu robią ci wektor bajtów i vice versa, | |
ale możesz dla swojego złożonego typu zdefiniować w global scopie własne funkcje | |
zwane write_object_bytes/read_object_bytes. | |
Jeśli moja templatka wykryje je tam gdzie jest wywołana, | |
to te funkcje będą wywołane zamiast np. domyślnego memcpy dla PODów. | |
Mam sobie zwykły obiekt.h. | |
Obok jest obiekt.hpp, | |
a w środku moje własne implementacje write_object_bytes/read_object_bytes dla klasy obiekt. | |
obiekt.hpp z założenia includuję tylko w serializacja.cpp, | |
żeby nie wrzucać wszędzie indziej niepotrzebnego kodu. | |
Wróćmy do crash.cpp. | |
Wywołuję tam write_bytes na obiekt z pewnego trywialnego powodu. | |
Nie ma tam jednak wywołania do read_bytes. | |
I kurwa zapomniałem do crash.cpp wrzucić obiekt.hpp żeby się poprawnie zapisał do bajtów | |
moimi customowymi funkcjami. | |
Kod się jednak zbudował, bo domyślny behaviour mojego serializatora też będzie działać, | |
a już na pewno powinien działać bez crasha, w przeciwnym wypadku jest wywalany static_assert. | |
Rezultat? | |
W serializacja.cpp, poprawnie includuję obiekt.hpp i wywołuję write_bytes oraz read_bytes | |
z widocznymi w global scopie write_object_bytes/read_object_bytes. | |
ALE, wcześniejsza kompilacja pliku crash.cpp striggerowała instantiację write_bytes | |
BEZ customowego write_object_bytes w obiekt.hpp (bo zapomniałem go wrzucić). | |
Rezultat? | |
W serializacja.cpp, read_bytes dla obiekt skompilował się z customowym read_object_bytes, | |
podczas gdy write_bytes dla obiekt skompilował się z domyślnym zachowaniem, | |
mimo że w scopie był widoczny customowy writer, | |
tylko dlatego że wcześniej w crash.cpp został już zinstantiatyzowany bez niego. | |
To poskutkowało w asymetrycznym cyklu read/write w serializacja.cpp - i mamy crasha. | |
Rozwiązanie jest proste, trzeba po prostu wrzucić po ludzku do obiekt.h forward-deklaracje | |
dla write_object_bytes/read_object_bytes, | |
żeby każdy compilation unit który używa obiekt widział zawsze że ma on customowe i/o. | |
No ale zajebałem i tego nie zrobiłem. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment