GNOME Bugzilla – Bug 624269
Cannot pass NULL to SourceLanguageManager::guess_language
Last modified: 2010-07-19 08:19:15 UTC
In the SourceLanguageManager, there's supposed to be a "guess_language" function with the following implementation: Glib::RefPtr<SourceLanguage> SourceLanguageManager::guess_language(const Glib::ustring& filename, const Glib::ustring& content_type) { Glib::RefPtr<SourceLanguage> retvalue = Glib::wrap(gtk_source_language_manager_guess_language(gobj(), filename.c_str(), content_type.c_str())); if(retvalue) retvalue->reference(); //The function does not do a ref for us. return retvalue; } The semantics are supposed to be that you pass in both parameters, but only one or the other are non-NULL (it doesn't know what to do if you specify both or neither). However, if you actually try to call it with NULL for either one of the two values, you fail with: terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_S_construct NULL not valid Whereas if you pass in an empty string instead, you fail differently with: (algoviz:12581): GtkSourceView-CRITICAL **: gtk_source_language_manager_guess_language: assertion `(filename == NULL || *filename != 0) && (content_type == NULL || *content_type != 0)' failed I've confirmed that this is just a mapping error by replacing the content_type.c_str() call with "NULL" directly in the source code, and it worked fine after that. But I thought I'd point this bug, since the function is pretty useless the way it is right now since it's uncallable.
(In reply to comment #0) > In the SourceLanguageManager, there's supposed to be a "guess_language" > function with the following implementation: > > > Glib::RefPtr<SourceLanguage> SourceLanguageManager::guess_language(const > Glib::ustring& filename, const Glib::ustring& content_type) > { > > Glib::RefPtr<SourceLanguage> retvalue = > Glib::wrap(gtk_source_language_manager_guess_language(gobj(), filename.c_str(), > content_type.c_str())); > if(retvalue) > retvalue->reference(); //The function does not do a ref for us. > return retvalue; > } > > > The semantics are supposed to be that you pass in both parameters, but only one > or the other are non-NULL (it doesn't know what to do if you specify both or > neither). Well, that is not true - the only forbidden situation is passing invalid string as both parameters (where by invalid I mean that either is NULL or "" - both are treated as invalid). See: http://git.gnome.org/browse/gtksourceview/tree/gtksourceview/gtksourcelanguagemanager.c?id=c5afa6d8c8145942eac6448dde1dde6824465a4b#n634 > However, if you actually try to call it with NULL for either one of > the two values, you fail with: > > terminate called after throwing an instance of 'std::logic_error' > what(): basic_string::_S_construct NULL not valid > Seems that you probably are passing NULL to Glib::ustring constructor which passes it to std::string constructor, which does not like NULL strings. Compile and run this code to see it: #include <iostream> #include <string> int main() { std::string str (0); std::cout << str << std::endl; } > Whereas if you pass in an empty string instead, you fail differently with: > > (algoviz:12581): GtkSourceView-CRITICAL **: > gtk_source_language_manager_guess_language: assertion `(filename == NULL || > *filename != 0) && (content_type == NULL || *content_type != 0)' failed > > I've confirmed that this is just a mapping error by replacing the > content_type.c_str() call with "NULL" directly in the source code, and it > worked fine after that. But I thought I'd point this bug, since the function is > pretty useless the way it is right now since it's uncallable. If such assertion popped, then that means that filename and content_type parameters are both invalid. Before you call the guess_language check the passed strings if they are not empty. Something like this: Glib::ustring filename (get_filename_from_somewhere ()); Glib::ustring content_type (get_content_type_from_somewhere ()); if (!filename.empty () || !content_type.empty ()) { lang = lang_manager->guess_language (filename, content_type); } else { // error - both strings are empty. }
I'm saying it happens even if only ONE of them is invalid. For example, the following line: Glib::RefPtr<gtksourceview::SourceLanguage> source_language = source_language_manager->guess_language("test.cpp", NULL); AND the following line: Glib::RefPtr<gtksourceview::SourceLanguage> source_language = source_language_manager->guess_language("test.cpp", ""); Both fail at runtime. The only way to actually call this function with one parameter only is to go Glib::RefPtr<gtksourceview::SourceLanguage> source_language = source_language_manager->guess_language(file, " "); at which point it works fine. Maybe this is how it is intended? But that is not made clear anywhere at all, and it seems like a rather silly workaround since the C version will gladly take the first possibility.
(In reply to comment #2) > I'm saying it happens even if only ONE of them is invalid. For example, the > following line: > > Glib::RefPtr<gtksourceview::SourceLanguage> source_language = > source_language_manager->guess_language("test.cpp", NULL); > This is programming error, so that won't work. Instead of NULL (or 0), Glib::ustring() or just "" should be passed. > AND the following line: > > Glib::RefPtr<gtksourceview::SourceLanguage> source_language = > source_language_manager->guess_language("test.cpp", ""); > > Both fail at runtime. The only way to actually call this function with one > parameter only is to go > > Glib::RefPtr<gtksourceview::SourceLanguage> source_language = > source_language_manager->guess_language(file, " "); > Now I see it. This assertion in C function gtk_source_language_manager_guess_language(): g_return_val_if_fail ((filename == NULL || *filename != 0) && (content_type == NULL || *content_type != 0), NULL); is probably a culprit. I'll ask gtksourceview maintainers if there should be `||' instead of `&&'. If not - I'll add overloads for both NULL parameters.
(In reply to comment #3) > (In reply to comment #2) > > I'm saying it happens even if only ONE of them is invalid. For example, the > > following line: > > > > Glib::RefPtr<gtksourceview::SourceLanguage> source_language = > > source_language_manager->guess_language("test.cpp", NULL); I am surprised that that even compiles. Does it really? Yes, in general, it's easiest if the C functions treat "" and 0 in the same way, but they often forget to.
(In reply to comment #4) > (In reply to comment #3) > > (In reply to comment #2) > > > I'm saying it happens even if only ONE of them is invalid. For example, the > > > following line: > > > > > > Glib::RefPtr<gtksourceview::SourceLanguage> source_language = > > > source_language_manager->guess_language("test.cpp", NULL); > > I am surprised that that even compiles. Does it really? It just uses Glib::ustring (const char*) constructor. Now I'm waiting for response in https://bugzilla.gnome.org/show_bug.cgi?id=624287
The assertion was fixed in gtksourceview (see bug 624284) and will be available in gtksourceview-3.0, so gtksourceviewmm-3.0 won't need the fix. As of gtksourceviewmm-2.0 - I'll change guess_language() method definition in a way it will pass NULL to C function when empty string is passed to the method. I'll do it tomorrow evening.
Fixed in git - the change will be available in gtksourceviewmm-2.10.1 version when it is released.
Thanks, guys! I appreciate it.