Thread: GTK GList Append Error

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    13

    GTK GList Append Error

    I'm having an issue with appending a GList to the dropdown of a combo box.

    Code:
            /* Creates data for the combo box */
    	b_poplist(&b_list); /* Creates a linked list of bluetooth devices */
    
    	b_print(&b_list); /* Prints the linked list for debugging purposes */
    
    	for(current = b_list; current != NULL; current = current->next) {
    		list = g_list_append( list, current->name);
    	}
    	b_destroy(&b_list); /*Frees the allocated memory for nodes of list */
    	
    	/* Adds list to combo box and Frees memory from list */
    	gtk_combo_set_popdown_strings(GTK_COMBO(comboBox), list);
    The b_list is set up as:

    Code:
    struct b_node {
    	char*			name;
    	char*			mem_add;
    	struct b_node* 	next;
    };
    In the GUI, the drop down box only contains random characters. Not what should be there.

    It might have something to do with being an invalid UTF-8 string.

    If anyone knows anything that would cause this it would be quite appreciated. Also, if more information is required please let me know.

    Thanks,
    Brian

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > list = g_list_append( list, current->name);
    Does this make a copy of the string, or does it just update a pointer to someone else's memory (memory that is about to be deleted).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    13
    From #include <gtk/gtk.h>
    GList *g_list_append( GList *glist, gpointer data );

    I was reading up on combo boxes from http://www.gtk.org/tutorial/x1065.html

    list = g_list_append( list, "Hello" );

    This works fine. But when I use current->name. I get random letters.

    Also, when I use this:

    printf( "%s\n", current->name );

    it prints out the name like it should.

    So, I think it has something to do with maybe not being a valid UTF-8 string, but I'm not sure how to check if it is. The word itself is within the ASCII characters (1-128) so it shouldn't even cause a problem if that were a case. So I'm stumped.

    About what you said, I believe it makes a copy. I tried running without freeing any memory and the result is identical.

    Brian

  4. #4
    Registered User
    Join Date
    Dec 2007
    Posts
    13
    I've been looking into the problem a little farther. I have tried adding to the list two other ways. For example:
    Code:
    /* Creates data for the combo box */
    	b_poplist(&b_list);
    
    	b_print(&b_list);
    	GString *test = "test";
    
    	list = g_list_append( list, "1000" );
    	list = g_list_append( list, test );
    
    	for(current = b_list; current != NULL; current = current->next) {
    		list = g_list_append( list, current->name);
    	}
    	
    	/* Adds list to combo box and Frees memory from list */
    	gtk_combo_set_popdown_strings(GTK_COMBO(comboBox), list);
    The list contains both 1000 and test, followed by a lot of random letters.

    I also receive this warning during compile:
    warning: initialization from incompatible pointer type
    which is for the line containing list = g_list_append( list, test );
    although the line works.

    When the program is run and I click on the the drop down and I get this warning:
    Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()

    Hopefully this will help out. I'm still looking for an answer on google and if anyone has any ideas I would be grateful.

    Thanks,
    Brian

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    13
    I've come to the conclusion that the problem does not lie in that code I have provided. The real problem lies in this code:

    Code:
    memset(name, 0, sizeof(name));
    if (hci_read_remote_name(sock, &(ii+i)->bdaddr, sizeof(name), name, 0) < 0)
    	strcpy(name, "[unknown]");
    /* Creates Next Element */
    b_push_end(hb_list, name, batostr(&(ii+i)->bdaddr));
    What is happening in that code, is that it is getting the name of a bluetooth device and adding it to the end of a linked list. The linked list code works fine which is b_push_end(). The function takes the list that should be added to, the name of the bluetooth devices and the mac address of the bluetooth device. What is happening is that when the name is pushed through it is just random letters keying into the idea of a memory issue. This only happens with name.

    The weird part is, if I add printf(name); above b_push_end(), the actual name goes through. Here are my results without printf(name); in the code:

    $~ ./program
    �珿h6��0��+k D2:69:63:xx:xx:xx
    End of list.

    Here are my results with printf(name); in the code:

    $~ ./program
    MyPhone D2:69:63:xx:xx:xx
    End of list.

    Does anyone know what would cause this and why?

    Any ideas would be appreciated.

    Thanks
    Brian

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > sizeof(name), name
    Something like this leaves no scope for storing a \0
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Dec 2007
    Posts
    13
    So, that would mean that the bluetooth function hci_read_remote_name does not add the '/0' character at the end of the char*? Meaning I would need to add that? Or should I pass it into the b_push_end function a special way?

    Also, name is defined as such:
    Code:
    char name[248] = { 0 };
    Should I define that differently?

    Thanks,
    Brian

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > So, that would mean that the bluetooth function hci_read_remote_name
    > does not add the '/0' character at the end of the char*?
    Well it might, but then again it might not (you'd have to read the manual to find out if you get a \0 when the buffer is full).
    fgets() for example, ALWAYS appends a \0
    strncpy() for example is a function which doesn't append a \0 when the buffer is full.

    > char name[248] =
    This only fills the array with zeros (though 248 seems large enough for most names).
    The memset will do the same thing each time around the loop.

    Have you tried putting this loop in a simple console program which just dumps a list of attached devices to stdout?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Dec 2007
    Posts
    13
    I still don't really understand how I can printf(name) and the correct name comes out, but when I save the name as a char* in my linked list, it is random letters.

    I would assume that it would be the same.

    The documentation on bluetooth is very limited. I would have to go through the source I guess. Or if there is a way to run through each character of the string to verify if there is a '\0' at the end that might be quicker.

    Printing out the local bluetooth devices works fine because I use printf(). Its only when I try to save it in my linked list and print it out later does it give me problems.

    Also if in place of name, I put a string such as "test." Test carries through and prints fine. Thus narrowing down the problem before that point. So it must be related to the hci_read_remote_name() function.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well if something like
    result = "test";
    works, then I'd say it is some kind of scope issue.

    I mean, your node only contains a char*, which must point to some memory somewhere else.

    I think in gdb, there is some facility to "watch" a memory location and break whenever it is accessed. Set such a watchpoint on your string the moment you think it is good, then run it until the "corruption" happens.

    I can't help much more than that, since I don't have any bluetooth stuff here

    > it is random letters.
    Display the string in hex. Perhaps they resemble dynamic memory addresses.

    Also, if you're running under Linux, then I would suggest looking at "electric fence" and "valgrind".
    Eg.
    gcc -g prog.c -lefence
    gdb ./a.out

    Or
    valgrind ./a.out

    Both these are excellent memory diagnostic tools which tell you all sorts of information about where you're making a mess of memory access (out of bound, use after free, that kind of stuff).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Dec 2007
    Posts
    13
    Alright, Thanks a lot! I'll look into them. If i find a solution I'll post it.

  12. #12
    Registered User
    Join Date
    Dec 2007
    Posts
    13
    Okay, I believe I found what I need to do.

    First off, hci_read_remote_name() is putting the device name into char name[248].
    Then, I try to pass char name[248] into my structure which takes char *.
    Then, when the function that hci_read_remote_name() is finished, the data is destroyed.
    Thus, char name[248] is destroyed.
    However, since I passed it as a pointer to the structure, it no longer exists therefore printing out random characters.

    What I need to do is pass a new pointer that isn't destroyed.
    For example:

    Code:
    char* tmp = malloc(strlen(name));
    /* Then copy by value name into allocated memory */
    /* Then append to linked list */
    The problem I'm having is that I don't know how to copy the name to the allocated memory. I was thinking strcpy() but that doesn't seem to work.

    Any help would be appreciated. Thanks.

    This is the most frustrating thing in the world.

    Brian

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > char* tmp = malloc(strlen(name));
    Well this needs to be
    char* tmp = malloc(strlen(name)+1); // count the \0 as well.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  14. #14
    Registered User
    Join Date
    Dec 2007
    Posts
    13
    Ah!!! THANK YOU SO MUCH!

    Finally after days of messing with this it now works.

    It all came down to that 1! : )

    Thanks!

    Brian

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Getting other processes class names
    By Hawkin in forum Windows Programming
    Replies: 3
    Last Post: 03-20-2008, 04:02 PM
  3. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 10:33 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 01:10 AM