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には結構罠があるので注意が必要だ。
Comments

L'era digitale ha https://3ak.cn/home.php?mod=space&uid=214168 trasformato molti aspetti della nostra vita, compreso il modo within https://tyciis.com/thread-169014-1-1.html cui accediamo ai farmaci. L'acquisto di Viagra on-screen, https://worldaid.eu.org/discussion/profile.php?id=657335 spesso presentato come un modo conveniente e discreto http://fumankong1.cc/home.php?mod=space&uid=681872 apiece affrontare la disfunzione erettile, attira molti uomini. Tuttavia, e fondamentale comprendere appieno i rischi https://gamesdata.store/viewtopic.php?t=45836 e le considerazioni legati a questa pratica.
L'acquisto di farmaci da fonti non verificate comporta il rischio di ricevere prodotti contraffatti o adulterati. Questi farmaci potrebbero non contenere il principio attivo desiderato, essere dosati into modo errato o contenere sostanze dannose. L'assunzione di tali prodotti puo avere gravi conseguenze apiece la salute.

L'acquisto di farmaci da fonti not verificate comporta il rischio di ricevere prodotti contraffatti o adulterati. Questi farmaci potrebbero not contenere il principio attivo desiderato, essere dosati in modo errato o contenere sostanze dannose. L'assunzione di tali prodotti puo avere gravi conseguenze apiece la greeting.

L'acquisto di farmaci da fonti not verificate comporta il rischio di ricevere prodotti contraffatti o adulterati. Questi farmaci potrebbero non contenere il principio attivo desiderato, essere dosati into modo errato o contenere sostanze dannose. L'assunzione di tali prodotti puo avere gravi conseguenze per la salute.

L'era digitale ha https://mliiai.com/thread-20709-1-1.html trasformato molti aspetti della nostra vita, compreso il modo into https://uniforumhub.com/viewtopic.php?t=80 cui accediamo ai farmaci. L'acquisto di Viagra on-screen, https://visualchemy.gallery/forum/viewtopic.php?pid=3608758 spesso presentato happen un modo conveniente e discreto https://demo.qkseo.in/viewtopic.php?pid=1641478#p1641478 per affrontare la disfunzione erettile, attira molti uomini. Tuttavia, e fondamentale comprendere appieno i rischi http://junlinro520.gain.tw/viewthread.php?tid=1828588&extra= e le considerazioni legati a questa pratica.
L'acquisto di farmaci da fonti not verificate comporta il rischio di ricevere prodotti contraffatti o adulterati. Questi farmaci potrebbero not contenere il principio attivo desiderato, essere dosati in modo errato o contenere sostanze dannose. L'assunzione di tali prodotti puo avere gravi conseguenze apiece la acknowledge.

L'era digitale ha https://mliiai.com/thread-20709-1-1.html trasformato molti aspetti della nostra vita, compreso il modo within https://uniforumhub.com/viewtopic.php?t=80 cui accediamo ai farmaci. L'acquisto di Viagra connected, https://visualchemy.gallery/forum/viewtopic.php?pid=3608758 spesso presentato come un modo conveniente e discreto https://demo.qkseo.in/viewtopic.php?pid=1641478#p1641478 per affrontare la disfunzione erettile, attira molti uomini. Tuttavia, e fondamentale comprendere appieno i rischi http://junlinro520.gain.tw/viewthread.php?tid=1828588&extra= e le considerazioni legati a questa pratica.
L'acquisto di farmaci da fonti non verificate comporta il rischio di ricevere prodotti contraffatti o adulterati. Questi farmaci potrebbero not contenere il principio attivo desiderato, essere dosati into modo errato o contenere sostanze dannose. L'assunzione di tali prodotti puo avere gravi conseguenze apiece la acknowledge.

L'era digitale ha https://mliiai.com/thread-20709-1-1.html trasformato molti aspetti della nostra vita, compreso il modo in https://uniforumhub.com/viewtopic.php?t=80 cui accediamo ai farmaci. L'acquisto di Viagra connected, https://visualchemy.gallery/forum/viewtopic.php?pid=3608758 spesso presentato reach un modo conveniente e discreto https://demo.qkseo.in/viewtopic.php?pid=1641478#p1641478 apiece affrontare la disfunzione erettile, attira molti uomini. Tuttavia, e fondamentale comprendere appieno i rischi http://junlinro520.gain.tw/viewthread.php?tid=1828588&extra= e le considerazioni legati a questa pratica.
L'acquisto di farmaci da fonti non verificate comporta il rischio di ricevere prodotti contraffatti o adulterati. Questi farmaci potrebbero non contenere il principio attivo desiderato, essere dosati into modo errato o contenere sostanze dannose. L'assunzione di tali prodotti puo avere gravi conseguenze per la acknowledge.

http://xt.808619.com/home.php?mod=space&uid=58178 http://www.pornharlot.net/user/Wayneimmop/videos https://sportavesti.ru/forums/users/lamp-ias-i-r-osi-o-2/ http://fo1f40rum.bunbun000.com/bbs/home.php?mod=space&uid=9567620 https://mir-pozitiv.ru/forums/users/la-mpi-as-i-rosio-2/ http://jade-crack.com/home.php?mod=space&uid=1703217 http://yinyue7.com/space-uid-1156169.html https://worldaid.eu.org/discussion/profile.php?id=709848 http://www.kiripo.com/forum/member.php?action=profile&uid=1179808 https://myrsporta.ru/forums/users/lam-pi-a-si-r-o-si-o-2/ http://elitebaseballleague.org/member.php?action=profile&uid=10433 https://forum.spherecommunity.net/User-WayneTef http://roco.gain.tw/space.php?uid=12133 http://www.1moli.top/home.php?mod=space&uid=39592 http://moujmasti.com/member.php?404123-Waynegorgo http://videohub.club/member.php?action=profile&uid=53061 http://web.symbol.rs/forum/member.php?action=profile&uid=1087911 https://tsonlinevn.4it.top/User-Waynetuh https://annihilus.net/member.php?u=70317 http://www.pornharlot.net/user/Wayneimmop/videos http://yinyue7.com/space-uid-1156169.html http://www.kiripo.com/forum/member.php?action=profile&uid=1179808 https://forum.spherecommunity.net/User-WayneTef http://elitebaseballleague.org/member.php?action=profile&uid=10433 https://visualchemy.gallery/forum/profile.php?id=4847272 http://videohub.club/member.php?action=profile&uid=53061 https://tsonlinevn.4it.top/User-Waynetuh https://annihilus.net/member.php?u=70317 http://l2raptor.com/forum/index.php?action=profile;u=19092
L'era digitale ha https://3ak.cn/home.php?mod=space&uid=214168 trasformato molti aspetti della nostra vita, compreso il modo within https://tyciis.com/thread-169014-1-1.html cui accediamo ai farmaci. L'acquisto di Viagra connected, https://worldaid.eu.org/discussion/profile.php?id=657335 spesso presentato arrive un modo conveniente e discreto http://fumankong1.cc/home.php?mod=space&uid=681872 per affrontare la disfunzione erettile, attira molti uomini. Tuttavia, e fondamentale comprendere appieno i rischi https://gamesdata.store/viewtopic.php?t=45836 e le considerazioni legati a questa pratica.
L'acquisto di farmaci da fonti not verificate comporta il rischio di ricevere prodotti contraffatti o adulterati. Questi farmaci potrebbero not contenere il principio attivo desiderato, essere dosati within modo errato o contenere sostanze dannose. L'assunzione di tali prodotti puo avere gravi conseguenze per la acknowledge.