SFML community forums
Help => System => Topic started by: Svenstaro on February 07, 2011, 04:22:34 am
-
SetString on a sf::Text in sfml2 gets me this
terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid
This only happens on a mingw compiled version of my program. A native GCC version doesn't show this problem. The issue likely is that mingw only really has the "C" locale and my environment wants my local locale.
Running the mingw generated executable in wine with LC_ALL=C works. However, I think this should be fixed in SFML itself. The code in Utf.cpp tries to handle this problem, but somehow fails still. Shouldn't it return std::locale("C") if there is a problem?
Also, somehow it never enters the catch block for me.
Laurent, can you look into this?
-
Also, somehow it never enters the catch block for me.
Does it really never enter it, or does it enter it and then throws a new exception? There's no reason that the code avoids the catch block on the first line. However it might do on the second one, because there's no catch block to catch it.
Can you tell me which lines work for you (ie. don't throw):
std::locale l1;
std::locale l2("");
std::locale l3("C");
-
As for the try-catch:
namespace
{
// Get the current global locale
std::locale GetCurrentLocale()
{
std::cout << "outside before" << std::endl;
try
{
std::cout << "try before" << std::endl;
return std::locale("");
}
catch (std::exception&)
{
// It seems that some implementations don't know the "" locale (Mac OS X, MinGW)
std::cout << "catch before" << std::endl;
return std::locale();
}
}
}
Output:
outside before
try before
terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid
abnormal program termination
Your example:
#include <iostream>
#include <locale>
#include <exception>
int main(int argc, char* argv[]) {
try {
std::locale l1;
} catch (std::exception& e) {
std::cout << "l1 exploded" << std::endl;
std::cout << e.what() << std::endl;
}
try {
std::locale l2("");
} catch (std::exception& e) {
std::cout << "l2 exploded" << std::endl;
std::cout << e.what() << std::endl;
}
try {
std::locale l3("C");
} catch (std::exception& e) {
std::cout << "l3 exploded" << std::endl;
std::cout << e.what() << std::endl;
}
try {
std::locale l4("en_US");
} catch (std::exception& e) {
std::cout << "l4 exploded" << std::endl;
std::cout << e.what() << std::endl;
}
}
Output:
l2 exploded
locale::facet::_S_create_c_locale name not valid
l4 exploded
locale::facet::_S_create_c_locale name not valid
For the record, "" implicitly defaults to en_US on my system.
I propose that it should just use "C" whenever it runs on mingw. Mingw with the default stdlib that most people will use has no capability to do locales that I am aware of.
-
I propose that it should just use "C" whenever it runs on mingw
I propose to use the default constructor, which simply grabs the current global locale (which should be "C" with MinGW). If people want to use their system's preferred locale, they can call std::locale::global(std::locale("")), or pass std::locale("") to the SFML functions that deal with locales.
-
Well the problem is that my mingw defaults to my actual system locale, is that the default? I didn't do anything special. I just noticed that my application failed when cross-compiled. I also ran it in a native Windows environment and I get the same problem.
-
Well the problem is that my mingw defaults to my actual system locale, is that the default? I didn't do anything special.
What do you mean ? Does std::locale().name() returns "en_US"?
-
No, the default constructor of std::locale gives you the "C" locale while the "" constructor gives you the system default (e.g. "en_US"). This is a problem. Also, if the catch was executed, everything would work fine, but it appears to never be executed at all.
I'm not sure about the limitations of exception throwing in a dll, however. Might this be the reason it doesn't work?
-
No, the default constructor of std::locale gives you the "C" locale while the "" constructor gives you the system default (e.g. "en_US"). This is a problem.
Why is it a problem? That's what's specified in the standard.
Also, if the catch was executed, everything would work fine, but it appears to never be executed at all.
I'm not sure about the limitations of exception throwing in a dll, however. Might this be the reason it doesn't work?
I agree, this should be fixed in first place. I don't know if this is the reason, but you can easily check this by switching to static libraries.
However I'll change the code anyway, I think it's better to default to the current global locale, rather than the system's preferred locale. I think it's the default behaviour in the standard library (in iostreams).
-
I meant that it was a problem in this particular case, I don't consider it a problem in general.
Anyway, I'll just be waiting for your fix then.
-
I'm not sure about the limitations of exception throwing in a dll, however. Might this be the reason it doesn't work?
Unlikely. Exceptions work perfectly fine within DLLs and even across DLL boundaries if dynamic libgcc is used or if it has been patched to handle cross-module exceptions even without dynamic runtime library (TDM-GCC's libgcc is). What GCC version are you using?
-
I'm using mingw's gcc version 4.5.2. It is built with these settings: http://projects.archlinux.org/svntogit/community.git/tree/mingw32-gcc/trunk/PKGBUILD
I do wonder quite a bit about this behavior I'm seeing. Why doesn't the catch trigger? My build parameters should be fine.
Laurent, I made a minimal temporary fix by replacing the try-catch block with a simple return std::locale(). May I commit that to svn for now?
-
Laurent, I made a minimal temporary fix by replacing the try-catch block with a simple return std::locale(). May I commit that to svn for now?
Hmm no, I'll take 5 min to think about it and commit the clean solution once I'm 100% sure it's ok. Because std::locale's default constructor is very fast to execute, I think I can get rid of the whole GetDefaultLocale() thing if we choose this solution.
-
Done ;)
-
Yay, thanks for the quick fix.