{"id":70,"date":"2008-12-08T02:36:18","date_gmt":"2008-12-08T01:36:18","guid":{"rendered":"http:\/\/netrix.org.pl\/index.php\/2008\/12\/08\/wyrownanie-pamieci-dla-operatorow-new-i-new\/"},"modified":"2011-02-12T02:27:20","modified_gmt":"2011-02-12T01:27:20","slug":"wyrownanie-pamieci-dla-operatorow-new-i-new","status":"publish","type":"post","link":"https:\/\/netrix.org.pl\/index.php\/2008\/12\/08\/wyrownanie-pamieci-dla-operatorow-new-i-new\/","title":{"rendered":"Wyr\u00f3wnanie pami\u0119ci dla operator\u00f3w new i new[]"},"content":{"rendered":"<p>Gdy programuje si\u0119 co\u015b z u\u017cyciem funkcji wewn\u0119trznych kompilatora (Intrinsics) dla SSE, najlepiej jest gdy to, co do nich przekazujemy jest wyr\u00f3wnanie do 16 bajt\u00f3w, w przeciwnym wypadku powstaje problem z odczytaniem z pami\u0119ci i program si\u0119 wysypuje. Oczywi\u015bcie mo\u017cna korzysta\u0107 z funkcji \u0142aduj\u0105cych, kt\u00f3re przyjmuj\u0105 dane niewyr\u00f3wnane, ale funkcje te s\u0105 z oczywistych wzgl\u0119d\u00f3w wolniejsze. Do ustawienia wyr\u00f3wnania danych p\u00f3l stosuj\u0119 si\u0119 specjaln\u0105 deklaracje <em>__declspec(align(16))<\/em>, kt\u00f3r\u0105 nale\u017cy umie\u015bci\u0107 przed definicj\u0105 zmiennej (oczywi\u015bcie dotyczy to Microsoft Visual Studio).<\/p>\n<pre lang=\"cpp\">__declspec(align(16)) __m128 m_vector;<\/pre>\n<p>Niestety taka deklaracja dotyczy tylko obiekt\u00f3w na stosie. Te, kt\u00f3re s\u0105 tworzone na stercie, czyli przez <em>operator new<\/em> oraz <em>operator new[]<\/em>, nie zawsze s\u0105 wyr\u00f3wnane, dlatego trzeba zadba\u0107 o to samemu odpowiednio przeci\u0105\u017caj\u0105c te funkcje. Przeci\u0105\u017canie tych operator\u00f3w nie jest trudne. Oba przyjmuj\u0105 jako argument ilo\u015b\u0107 potrzebnego miejsca wyra\u017con\u0105 w bajtach, a zwracaj\u0105 wska\u017anik typu void, kt\u00f3ry zawiera adres odpowiedniego obszaru pami\u0119ci. Nag\u0142\u00f3wek jednego z tych operator\u00f3w wygl\u0105da nast\u0119puj\u0105co:<\/p>\n<pre lang=\"cpp\">void* operator new(const size_t nBytes)<\/pre>\n<p>W ciele takiej funkcji nale\u017cy zaalokowa\u0107 odpowiedni\u0105 ilo\u015b\u0107 miejsca, a nast\u0119pnie wyr\u00f3wna\u0107 wska\u017anik tak, aby dzieli\u0142 si\u0119 przez 16. Dopiero ten wska\u017anik mo\u017cna zwr\u00f3ci\u0107. Nale\u017cy oczywi\u015bcie pami\u0119ta\u0107 o zapisaniu gdzie\u015b poprzedniego wska\u017anika oraz o alokacji pami\u0119ci tak, \u017ceby po wyr\u00f3wnaniu nie wychodzi\u0107 poza przydzielony zakres.<br \/>\nW przypadku mojej funkcji adres jest zapisany przed wyr\u00f3wnanym adresem (dzi\u0119ki poradom <a href=\"http:\/\/forum.gamedev.pl\/index.php\/topic,8913.0.html\">koleg\u00f3w z forum <\/a>), a ilo\u015b\u0107 alokowanego miejsca jest wi\u0119ksza o rozmiar alokowanej struktury + 3 bajty.<\/p>\n<pre lang=\"cpp\">void* operator new(const size_t nBytes)\r\n{\r\n\u00a0char* ptr = new char[nBytes + sizeof(NVector) + 3];\r\n\u00a0unsigned int temp = reinterpret_cast<unsigned int>(ptr);  \/\/ Konwersja na posta\u0107 odpowiedni\u0105 do oblicze\u0144\r\n\u00a0unsigned int t = temp % 16;   \/\/ Obliczam o ile jest przesuni\u0119ty od wyr\u00f3wnania\r\n\u00a0temp += (t &lt; 13) ? (16 - t) : (32 - t);  \/\/ Dodaje odpowiednie przesuni\u0119cie do wska\u017anika\r\n\u00a0void* aPtr = reinterpret_cast<void*>(temp); \/\/ Zapis nowego wska\u017anika\r\n\u00a0temp -= sizeof(void*);\r\n\u00a0*reinterpret_cast<unsigned int*>(temp) = reinterpret_cast<unsigned int>(ptr); \/\/ Zapis poprzedniego wska\u017anika\r\n\u00a0return aPtr;\r\n}\r\n<\/pre>\n<p>NVector jest klas\u0105, w kt\u00f3rej umie\u015bci\u0142em ten operator. Liczba 13 wyst\u0119puj\u0105ca przy por\u00f3wnywaniu w powy\u017cszym kodzie reprezentuje przesuni\u0119cie, dla kt\u00f3rego nie jest mo\u017cliwe zapisanie wska\u017anika przed najbli\u017cszym wyr\u00f3wnaniem, dlatego trzeba doda\u0107 wi\u0119cej. Operator new[]wygl\u0105da identycznie, dlatego mo\u017cna w nim wywo\u0142a\u0107 powy\u017csz\u0105 funkcj\u0119. Odpowiednik delete dla tego operatora wygl\u0105da nast\u0119puj\u0105co:<\/p>\n<pre lang=\"cpp\">\r\nvoid operator delete(void* p)\r\n{\r\n\tunsigned int temp = reinterpret_cast<unsigned int>(p) - sizeof(void*);\r\n\tchar* temp2 = reinterpret_cast<char*>(*reinterpret_cast<int*>(temp));\r\n\tdelete[] temp2;\r\n}\r\n<\/pre>\n<p>Powy\u017csza funkcja oblicza poprzedni wska\u017anik i korzystaj\u0105c z niego dealokuje obszar. Operator delete[] jest identyczny.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gdy programuje si\u0119 co\u015b z u\u017cyciem funkcji wewn\u0119trznych kompilatora (Intrinsics) dla SSE, najlepiej jest gdy to, co do nich przekazujemy jest wyr\u00f3wnanie do 16 bajt\u00f3w, w przeciwnym wypadku powstaje problem z odczytaniem z pami\u0119ci i program si\u0119 wysypuje. Oczywi\u015bcie mo\u017cna korzysta\u0107 z funkcji \u0142aduj\u0105cych, kt\u00f3re przyjmuj\u0105 dane niewyr\u00f3wnane, ale funkcje te s\u0105 z oczywistych wzgl\u0119d\u00f3w [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[179,84,85,86],"_links":{"self":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/70"}],"collection":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/comments?post=70"}],"version-history":[{"count":2,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/70\/revisions"}],"predecessor-version":[{"id":801,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/70\/revisions\/801"}],"wp:attachment":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/media?parent=70"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/categories?post=70"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/tags?post=70"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}