FName::GetPlainANSIString()で正しい文字列が取れない事がある

お急ぎのあなたのために、まずは結論。FNameが保持する文字列が必要な時はToString()で生成したFStringを使うべし。GetPlainANSIString()GetPlainWIDEString()を使うとハマるから止めといた方がいい。

Unreal Engine 4の軽量文字列クラスFName公式リファレンス)のGetPlainANSIString関数/GetPlainWIDEString関数で取得できる文字列ポインタには、そのFNameインスタンスが本来持っている文字列の一部しか入っていない事がある。恐らく仕様。以下が実証コード。

TArray<FName> Names;
Names.Add(FName(TEXT("Hoge_")));
Names.Add(FName(TEXT("Hoge_0000")));
Names.Add(FName(TEXT("Hoge_0001")));
Names.Add(FName(TEXT("Hoge_10")));
Names.Add(FName(TEXT("Hoge_1200")));
Names.Add(FName(TEXT("Hoge_1300")));
Names.Add(FName(TEXT("Hoge_9999")));
Names.Add(FName(TEXT("Hoge9999")));
 
for (const auto& Name : Names)
{
	UE_LOG(LogWindows, Log, TEXT("◆%s"), *Name.ToString());
	UE_LOG(LogWindows, Log, TEXT("  PlainAnsiString=%s (%p)"), *FString(Name.GetPlainANSIString()), Name.GetPlainANSIString());
	UE_LOG(LogWindows, Log, TEXT("  [FNameEntry]"));
	UE_LOG(LogWindows, Log, TEXT("    ComparisonIndex=%d"), Name.GetComparisonIndex());
	UE_LOG(LogWindows, Log, TEXT("      [ComparisonEntry]"));
	UE_LOG(LogWindows, Log, TEXT("        Address=%p"), Name.GetComparisonNameEntry());
	UE_LOG(LogWindows, Log, TEXT("        isWide=%d"), Name.GetComparisonNameEntry()->IsWide());
	UE_LOG(LogWindows, Log, TEXT("    DisplayIndex=%d"), Name.GetDisplayIndex());
	UE_LOG(LogWindows, Log, TEXT("      [DisplayEntry]"));
	UE_LOG(LogWindows, Log, TEXT("        Address=%p"), Name.GetDisplayNameEntry());
	UE_LOG(LogWindows, Log, TEXT("        isWide=%d"), Name.GetDisplayNameEntry()->IsWide());
	UE_LOG(LogWindows, Log, TEXT("    Number=%d"), Name.GetNumber());
}

実行結果を見ると、Hoge_10, Hoge_1200, Hoge_1300, Hoge_999で見事に同一のPlainAnsiStringが返ってきているのが分かる(★の部分)

LogWindows: ◆Hoge_
LogWindows:   PlainAnsiString=Hoge_ (000000021299B988)
LogWindows:   [FNameEntry]
LogWindows:     ComparisonIndex=1029720
LogWindows:       [ComparisonEntry]
LogWindows:         Address=000000021299B978
LogWindows:         isWide=0
LogWindows:     DisplayIndex=1029720
LogWindows:       [DisplayEntry]
LogWindows:         Address=000000021299B978
LogWindows:         isWide=0
LogWindows:     Number=0
LogWindows: ◆Hoge_0000
LogWindows:   PlainAnsiString=Hoge_0000 (000000021299B9A0)
LogWindows:   [FNameEntry]
LogWindows:     ComparisonIndex=1029721
LogWindows:       [ComparisonEntry]
LogWindows:         Address=000000021299B990
LogWindows:         isWide=0
LogWindows:     DisplayIndex=1029721
LogWindows:       [DisplayEntry]
LogWindows:         Address=000000021299B990
LogWindows:         isWide=0
LogWindows:     Number=0
LogWindows: ◆Hoge_0001
LogWindows:   PlainAnsiString=Hoge_0001 (000000021299B9C0)
LogWindows:   [FNameEntry]
LogWindows:     ComparisonIndex=1029722
LogWindows:       [ComparisonEntry]
LogWindows:         Address=000000021299B9B0
LogWindows:         isWide=0
LogWindows:     DisplayIndex=1029722
LogWindows:       [DisplayEntry]
LogWindows:         Address=000000021299B9B0
LogWindows:         isWide=0
LogWindows:     Number=0
LogWindows: ◆Hoge_10
LogWindows:   PlainAnsiString=Hoge (000000021299B9E0)…★
LogWindows:   [FNameEntry]
LogWindows:     ComparisonIndex=1029723
LogWindows:       [ComparisonEntry]
LogWindows:         Address=000000021299B9D0
LogWindows:         isWide=0
LogWindows:     DisplayIndex=1029723
LogWindows:       [DisplayEntry]
LogWindows:         Address=000000021299B9D0
LogWindows:         isWide=0
LogWindows:     Number=11
LogWindows: ◆Hoge_1200
LogWindows:   PlainAnsiString=Hoge (000000021299B9E0)…★
LogWindows:   [FNameEntry]
LogWindows:     ComparisonIndex=1029723
LogWindows:       [ComparisonEntry]
LogWindows:         Address=000000021299B9D0
LogWindows:         isWide=0
LogWindows:     DisplayIndex=1029723
LogWindows:       [DisplayEntry]
LogWindows:         Address=000000021299B9D0
LogWindows:         isWide=0
LogWindows:     Number=1201
LogWindows: ◆Hoge_1300
LogWindows:   PlainAnsiString=Hoge (000000021299B9E0)…★
LogWindows:   [FNameEntry]
LogWindows:     ComparisonIndex=1029723
LogWindows:       [ComparisonEntry]
LogWindows:         Address=000000021299B9D0
LogWindows:         isWide=0
LogWindows:     DisplayIndex=1029723
LogWindows:       [DisplayEntry]
LogWindows:         Address=000000021299B9D0
LogWindows:         isWide=0
LogWindows:     Number=1301
LogWindows: ◆Hoge_9999
LogWindows:   PlainAnsiString=Hoge (000000021299B9E0)…★
LogWindows:   [FNameEntry]
LogWindows:     ComparisonIndex=1029723
LogWindows:       [ComparisonEntry]
LogWindows:         Address=000000021299B9D0
LogWindows:         isWide=0
LogWindows:     DisplayIndex=1029723
LogWindows:       [DisplayEntry]
LogWindows:         Address=000000021299B9D0
LogWindows:         isWide=0
LogWindows:     Number=10000
LogWindows: ◆Hoge9999
LogWindows:   PlainAnsiString=Hoge9999 (000000021299B9F8)
LogWindows:   [FNameEntry]
LogWindows:     ComparisonIndex=1029724
LogWindows:       [ComparisonEntry]
LogWindows:         Address=000000021299B9E8
LogWindows:         isWide=0
LogWindows:     DisplayIndex=1029724
LogWindows:       [DisplayEntry]
LogWindows:         Address=000000021299B9E8
LogWindows:         isWide=0
LogWindows:     Number=0

FNameはハッシュ付き文字列として実装されている。文字列はFNameの共用領域に格納され、各FNameインスタンスはその文字列格納領域へのインデックス=ハッシュを保持してる。FNameの同士の比較は互いのハッシュの比較、つまり整数の比較に還元されるため、通常の文字列比較より速いって仕掛けなんですな。

ただ、このハッシュ生成方法がちょっと曲者で、文字列がアンダースコア+ゼロ詰めされていない数値で終わっていたら、その部分を除いた文字列を共用領域に格納し、数値は各FNameインスタンスで保持するという方法なのだ。割と最近のバージョンアンプで変わったらしい(知人曰く4.12あたりで変わった気がすると)。なかなか破壊的な変更をしてくださりやがるな!言葉だと分かりにくいので図を作ってみた。

図を踏まえつつ改めて実行結果を見てみると、条件に合致するHoge_10, Hoge_1200, Hoge_1300, Hoge_999の中身が、その通りになっている事がお分かりいただけよう。Numberが実際の数値+1されているのは、これまた仕様で、数値分割条件を満たさないFNameインスタンス(Number == 0)との区別の為っぽい。

UE4では生成されたオブジェクトのインスタンスに対し、オブジェクト名+連番の名前を自動付与するため、大規模な開発になるとFName文字列ストアの肥大化が無視できなくなり、保持方法を変更したのだと思われる。

こんな格納の仕方で大丈夫なの!?と思うが、ふつーにFNameを使う分には何の問題もない。や、正確には大丈夫じゃなかったからこの記事書いてる訳だけど、文字列の生ポインタ取ってこねくり回すような事をしなければ大丈夫。FName文字列に対して低レベルな操作を行いたい時は、ToString()関数で生成したFStringに対して行う事をオススメする。エンジンのコードを見てもらうと分かるが、ComparisonIndexの文字列にアンダースコアと数値をくっつけて元の文字列を復元してやがるので(笑)

ちなみに、実行結果内のDisplayIndexというのは、名前の通り表示用の文字列へのインデックス。簡単に言えば、FName生成時に与えられた文字列のインデックスである。FNameは基本的にcase-preserving(内部的には大文字小文字を区別するが対外的には区別せずに扱う)なので、比較用と表示用で別々の文字列を持つ必要がある訳だ。知らずに使ってると、これも地味にハマりポイントかも。

FName abc(TEXT("abc"));
FName ABC(TEXT("ABC"));
UE_LOG(LogWindows, Log, TEXT("%s %s %s"), *abc.ToString(), (abc == ABC ? TEXT("==") : TEXT("!=")), *ABC.ToString());

念のため上記コードで確認したら、LogWindows: abc == ABCとなった。

掘ってみるとFNameには結構罠があるので注意が必要だ。

скачать лучшие фильмы на телефон http://nacionrolera.org/foro/viewtopic.php?f=1210&t=40491 Result: использован никнейм “Davidedups”; <Lang>es]; вошли; успех - запостили в раздел “Fantasia: en general”; промокод на скидку алиэкспресс 2022 активные бигам купон на скидку https://www.ldvd.nl/comment/reply/55914?quote=1 Result: ОШИБКА СЕРВЕРА (host www.ldvd.nl:443); использован никнейм “JosephUnlal”; <Lang>nl]; вошли; успех; ютека промокод на скидку

все инструменты купон на скидку https://ide-ai.online/member.php?action=profile&uid=2444 казань экспресс скидки на заказ промокод https://www.feeder.mobi/members/julesculse/profile/ мореон промокод на скидку https://nitroporno.com/user/JamesBef/ индексирование страницы это

купить купон со скидкой http://ukrpart.org/index.php?subaction=userinfo&user=astonishingalma остин промокод на скидку 2022 http://ksjy88.com/home.php?mod=space&uid=3647797 поисковая индексация сайта http://forum.myslash.ru/profile.php?mode=viewprofile&u=54058 конторы с бездепозитным бонусом

сервис прогона сайта промокод на скидку на озоне сегодня экзист купоны на скидку http://www.postcount.net/forum/member.php?117480-JeffreyVat что значит индексация сайта http://www.kbszw.com/home.php?mod=space&uid=19263

алло пицца промокод на скидку http://musecollectors.org/community/profile/zacherycer/ деливери скидка на первый заказ промокод прогон статейный сайт https://cq.x7cq.vip/home.php?mod=space&uid=9169813 качественный прогон сайта https://www.hubtamil.com/talk/member.php?1701701-Mycsgonow

автоматический прогон сайта по трастовым сайтам пробный прогон сайта как узнать индексацию сайта в яндексе http://polegasm.net/index.php/forum/welcome-mat/119004 прогон сайта в трастовых

купон на скидку товара https://google.com.bo/url?q=https://doctorlazuta.by/ скидка в эльдорадо промокод 2022 аскона промокод на скидку http://foru1f40m.bunbun000.com/bbs/home.php?mod=space&username=Kennethpoiva индексация сайта в поиске

https://www.battle-scape.com/members/255548-RalphMER&tab=vbs-notifications http://www.hellojammu.news/2018/10/Indian-American-invest-USD-60-mn-in-medical-device-company.html

1 | | 2024-09-24 14:22 | reply

сео прогон сайта https://forum.bedwantsinfo.nl/newthread.php?fid=2 прогон сайта бзли прогон сайта по каталогам онлайн http://diplomka.jakubfiser.com/clanky/non-parametric-sampling-prvni-verze прогон по сайтам дешево

купон на скидку косметика онлайн прогон сайта по каталогам бесплатно htaccess запретить индексацию сайта https://www.rs6.com/member.php/747561-Henrybrugh как ускорить индексацию сайта в google http://test-sida.noads.biz/home.php?mod=space&uid=62978

ускорить индексацию страницы где размещать статьи продвижения прошел ли сайт индексацию http://tmml.top/home.php?mod=space&uid=97234 магазин промокод на скидку http://www.jkmulti.com/bbs/board.php?bo_table=free&wr_id=1755651

якитория промокод на скидку на доставку https://kamchaty.ru/user/Chrisevaft/ прогон по сайтам отзывов самокат скидка на заказ промокод https://atoms.rocks/member.php?action=profile&uid=42074 скидка на яндекс такси промокод 2022 https://flaxeco.com/user/DoctorLazutaOr/

купон на скидку дома http://czechmod.cz/profile.php?lookup=9821 купоны на скидку магнит 2022 прогон сайта в профилях http://bbs.ep360.cn/home.php?mod=space&uid=95479 скачать хороший фильм на телефон бесплатно

промокод в яблоке на скидку http://www.jindoushiqi.com/bbs/home.php?mod=space&uid=128148 что такое прогон сайта по соц закладками заказать прогон сайта по трастовым сайтам http://www.118btc.com/home.php?mod=space&uid=583314 бесплатно прогон сайта

хрумер программа для прогона сайта https://loansnearme.com.au/author/ralphepich/ купоны скидки онлайн https://google.com.sb/url?q=https://doctorlazuta.by/ промокод на скидку самокат https://www.google.li/url?q=https://doctorlazuta.by/ купон на скидку 1000 рублей https://m1bar.com/user/CharlesAlith/

купоны про на скидку прогон по трастовым сайта http://xinyue678.com/home.php?mod=space&uid=1124417 прогон сайт http://www.forumklassika.ru/member.php?u=152853 ускоренное индексирование сайта прогон сайта по социальным сетям

ставки на спорт букмекерские конторы фреш казино https://krtka.info/ бк букмекерская контора лучшие букмекерские конторы https://rumafia.news/ pin up casino top top почему в казино нет часов Лут Оксана Николаевна порно porno Яна Троянова porno Ангелина Гончаренко, хоккеистка казино рояль смотреть inform@rucriminal.info

http://site1112.ru

2 | | 2024-12-13 00:00 | reply

ai allowing nsfw nsfw ai story write http://salavat-ufa.ru/index.php?subaction=userinfo&user=adyhazo meowchat ai nsfw аналоги character ai без фильтра nsfw бесплатно https://deanzjsa96307.onesmablog.com/deepnude-the-ethical-and-social-dilemma-of-ai-driven-image-manipulation-70686484 nsfw ai chat на русском nsfw ai gif nsfw ai model nsfw ai text ai боты для бесплатного создания nsfw картинок anime nsfw ai generator nsfw loli ai

3 | | 2024-12-19 07:01 | reply

программа для прогона сайта по трастовым сайтам http://afpd.onlinebbs.ru/viewtopic.php?f=2&t=6746 прогон сайта по трастовым сайтам что это такое https://thetechmodders.com/forums/viewtopic.php?t=58157 гилмон в челябинске купоны скидки http://diplomka.jakubfiser.com/clanky/non-parametric-sampling-prvni-verze/ учи ру купоны на скидку http://miupsik.ru/forums/showthread.php?tid=348421

промокод на скидку в мвидео https://bongfood.kr/bbs/board.php?bo_table=free&wr_id=537318 программы для прогона по сайтам http://elka54.ru/forum/?PAGE_NAME=profile_view&UID=101719 ускоренная индексация сайта в поисковых системах http://baby123.cc/home.php?mod=space&uid=70474&do=profile бесплатный прогон сайтов

отзывы о статейном прогоне http://anima-rpg.com:/member.php?action=profile&uid=333659 ускоренное индексирование сайта в гугл прогон сайта по каталогам скачать https://build-info.biz.ua/wr_board/tools.php?event=profile&pname=CharlesGog индексирование страниц яндекс https://play.ntop.tv/user/DeweyGlile/

столплит промокод на скидку бездепозитные бонусы деньгами игровые автоматы игровые онлайн с бездепозитным бонусом http://www.clrobur.com/bbs/board.php?bo_table=free&wr_id=618507 купон на скидку хуавей https://thiamlau.com/forum/member.php?action=profile&uid=4285

каталоги для прогона сайта https://fm.xndl.com/home.php?mod=space&uid=637214 прогон сайта по трастовой базе http://ledyardmachine.com/forum/User-Jefferymaype видео купон на скидку https://www.uned-psicologia.com/index.php?action=profile;u=18260 скидки акции промокоды

купоны скидки телеграмм эльдорадо купон на скидку http://elymbmx.com/mybb/member.php?action=profile&uid=11343 прогон сайта по каталогам статей http://www.haoxin.city/home.php?mod=space&uid=188494&do=profile бесплатный прогон по каталогам сайтов http://perfectsolutionlabs.com/user/Jasperhut/

программа прогона сайт в бесплатных каталогах http://augaliukas.lt/index.php?subaction=userinfo&user=muddledgrandeur лента купоны на скидку день рождения продвижение вечными статьями https://lunar.az/user/Shawnjoith/ прогона по трастовым сайтам

прогон сайта по трастовым ссылкам http://forum.gold-forum.ru/index.php?showuser=19754 прогон сайта по каталогам статей http://mongdol.net/bbs/board.php?bo_table=free&wr_id=2866606 купоны на скидку здоровье http://gtamotors.ru/user/JasperceT/ хочу скидку промокод http://www.dong-joo.co.kr/bbs/board.php?bo_table=free&wr_id=667888 ? ? продвижение сайта с помощью статей

gama casino new casino https://th-royalgclub.com/ скачать pin casino casino бездепозитный https://kompromat1.online/ казино вулкан Елизавета Боярская казино регистрации 7k casino скачать ешь казино 1xbet скачать приложение на андроид 1xbet регистрация

http://filmkachat.ru




  • blog/2017/2017-01-20.txt
  • 最終更新: 2017-01-24 11:13
  • by Decomo