Pebble Menu Layer Crash - c

I've been designing a personal news feed app for the original pebble which displays news content in a menu layer. I have two C files, one which contains a window that displays a loading image and handles the data transfer between the js on the phone and my watch app. The data is saved into some extern variables which are shared between the files but is irrelevant in the example I show below (all of that works fine I believe).
I'm calling news_list_window_init() in my main .c file within a function when certain conditions are met. Right now I'm just trying to display a window with a scrollable menu to test that my menu looks acceptable. The problem I'm having is that my app crashes when I try to scroll. The window appears, all my menu items are there but when I scroll the app exists with:
ault_handling.c:78> App fault! {f5ec8c0d-9f21-471a-9a5c-c83320f7477d} PC: 0x800fd5b LR: ???
Program Counter (PC) : 0x800fd5b ???
Link Register (LR) : ??? ???
I've tested my .c file below independently, where I create a new project with only this code, comment out the non-relevant news_list.h and externs.h header files, and comment in the main function at the bottom of the file. This works fine, my menu scrolls and there are no crashes and everything looks fine.
I don't see how the problem could be in my main file, because the only function I call in it which is contained in this file is news_list_window_init(), moreover the menu does indeed display correctly. I can even close the app properly with the back button. Trying to scroll however crashes the application. I'm sort of at a loss as to what could be causing this error. Does anybody have any suggestions? Thanks!
This is the relevant .c file:
// news_list.c
#include "pebble.h"
#include "news_list.h"
#include "externs.h"
#define NUM_MENU_SECTIONS 1
static Window *news_list_window;
static MenuLayer *menu_layer;
static uint16_t menu_get_num_sections_callback(MenuLayer *menu_layer, void *data) {
return NUM_MENU_SECTIONS;
}
static uint16_t menu_get_num_rows_callback(MenuLayer *menu_layer, uint16_t section_index, void *data) {
return str_count; // Variable story count
}
static int16_t menu_get_header_height_callback(MenuLayer *menu_layer, uint16_t section_index, void *data) {
return MENU_CELL_BASIC_HEADER_HEIGHT;
}
static void menu_draw_header_callback(GContext* ctx, const Layer *cell_layer, uint16_t section_index, void *data) {
menu_cell_basic_header_draw(ctx, cell_layer, "Header");
}
static void menu_draw_row_callback(GContext* ctx, const Layer *cell_layer, MenuIndex *cell_index, void *data) {
menu_cell_basic_draw(ctx, cell_layer, "Menu Item", NULL, NULL);
}
static void menu_select_callback(MenuLayer *menu_layer, MenuIndex *cell_index, void *data) {
// Currently Empty
}
int16_t menu_get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context)
{
return 40;
}
static void news_list_window_load(Window *window) {
// Now we prepare to initialize the menu layer
Layer *window_layer = window_get_root_layer(window);
GRect bounds = layer_get_frame(window_layer);
// Create the menu layer
menu_layer = menu_layer_create(bounds);
menu_layer_set_callbacks(menu_layer, NULL, (MenuLayerCallbacks){
.get_num_sections = menu_get_num_sections_callback,
.get_num_rows = menu_get_num_rows_callback,
.get_header_height = menu_get_header_height_callback,
.draw_header = menu_draw_header_callback,
.draw_row = menu_draw_row_callback,
.select_click = menu_select_callback,
.get_cell_height = menu_get_cell_height_callback,
});
// Bind the menu layer's click config provider to the window for interactivity
menu_layer_set_click_config_onto_window(menu_layer, window);
layer_add_child(window_layer, menu_layer_get_layer(menu_layer));
}
static void news_list_window_unload(Window *window) {
// Destroy the menu layer
menu_layer_destroy(menu_layer);
}
void news_list_window_init() {
news_list_window = window_create();
window_set_window_handlers(news_list_window, (WindowHandlers) {
.load = news_list_window_load,
.unload = news_list_window_unload,
});
window_stack_push(news_list_window, true);
}
void news_list_window_deinit() {
window_destroy(news_list_window);
}
// int main(void) {
// news_list_window_init();
// app_event_loop();
// news_list_window_deinit();
// }
This is the relevant .h file:
// news_list.h
#ifndef NEWS_LIST_H
#define NEWS_LIST_H
// Public Function list
void news_list_window_init(void);
void news_list_window_deinit(void);
#endif

I've had this happen when I'm running really low on memory, or if I'm corrupting memory somehow.
I'd suggest checking all return values for NULL and logging and bailing if they are (menu_layer_create, malloc etc.).
Also, try logging how much free memory you have - if you are working on an original Pebble, and allocating large memory buffers for communication, you can very quickly run out of memory.
Finally, walk through all code that allocates and uses memory to be absolutely sure you are not accidentally writing past the end of an array, or passing a value allocated on the stack into a pebble call. I like to use calloc rather than malloc to be sure I don't think I have a value in a malloc'd structure when I don't.
I've been here before - it isn't easy, but likely totally unrelated to your UI code - the crash is just a symptom. If all else fails maybe post the complete code in github so that we can take a look at the complete app...
Damian

Related

How do I determine the source of this memory change/corruption?

I am currently developing a Vulkan program that I anticipate to use as a game engine, but I am far from my goal. As a first step, I'm just trying to render a triangle using a list of dynamic structures to get data such as vertices and shaders. To work around platform specific hurdles, I'm using GLFW to create windows and Vulkan surfaces.
Right now I'm trying to load SPIR-V shaders from a file and use them to create VkShaderModules which I will use in my render pipeline. Currently, the abstracted part of my code starts like this:
main.c
#include "application.h"
#include "config.h"
#include "engine_vulkan.h"
#include "glfw/glfw3.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
printf("VLK Engine - Version %s\n", VERSION_NUMBER);
if (enable_validation_layers) {
printf("Validation layers enabled.\n");
}
printf("\n");
struct VulkanData vulkan_data = {0};
struct Application app = {.window = NULL, .vulkan_data = &vulkan_data, .objects = NULL};
bool ret = application_init(&app);
if (ret == false) {
fprintf(stderr, "Cannot initialize applcation.\n");
return EXIT_FAILURE;
}
while (application_loopcondition(&app)) {
application_loopevent(&app);
}
application_close(&app);
return EXIT_SUCCESS;
}
application.c
#include "application.h"
#include "engine_object.h"
#include "engine_vulkan.h"
bool application_init(struct Application *app) {
bool ret;
// Initialize GLFW
glfwInit();
// Create window
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
app->window = glfwCreateWindow(800, 600, "Vulkan window", NULL, NULL);
if (app->window == NULL) {
fprintf(stderr, "Failed to create window.\n");
return false;
}
printf("Created window # 0x%p\n", app->window);
// Initialize game object list
objectlink_init(app);
// Create game objects
struct RenderObjectCreateInfo ro_create_info = {.vertex_shader_path = "shaders/shader.vert.spv",
.fragment_shader_path =
"shaders/shader.frag.spv",
.is_static = true};
struct RenderObject triangle = {0};
object_init(app, &ro_create_info, &triangle);
objectlink_add(app, &triangle);
// Init Vulkan
ret = vulkan_init(app);
if (!ret) {
fprintf(stderr, "Failed to initialize Vulkan.\n");
return false;
}
return true;
}
bool application_loopcondition(struct Application *app) {
// Close only if GLFW says so
return !glfwWindowShouldClose(app->window);
}
void application_loopevent(struct Application *app) {
// Poll for events like keyboard & mouse
glfwPollEvents();
}
void application_close(struct Application *app) {
// Destroy objects
objectlink_destroy(app);
// Close Vulkan instance
vulkan_close(app);
// End window & GLFW
glfwDestroyWindow(app->window);
glfwTerminate();
}
Important structures
struct Application {
GLFWwindow *window;
struct VulkanData *vulkan_data;
struct RenderObjectLink *objects;
};
struct RenderObject {
char *vertex_shader_path;
struct ShaderFile vertex_shader_data;
VkShaderModule vertex_shader;
char *fragment_shader_path;
struct ShaderFile fragment_shader_data;
VkShaderModule fragment_shader;
bool is_static;
};
struct RenderObjectCreateInfo {
char *vertex_shader_path;
char *fragment_shader_path;
bool is_static;
};
struct RenderObjectLink {
struct RenderObject *render_object;
struct RenderObjectLink *next;
};
The problem in my application comes when storing the VkShaderModules in my application structure. The way that my program is supposed to store information about objects is in the Application structure called app, in which it points to a linked list of RenderObjectLink in the objects field. My functions objectlink_init and objectlink_add work properly, however the data inside the structure the render_object field points to gets changed/corrupted when entering the GLFW functions glfwWindowShouldClose and glfwPollEvents.
Since those two functions are ran after initializing Vulkan and creating the shader modules, I've found with GDB that the Vulkan functions are working properly and that my data structures are only getting corrupted when running the GLFW loop functions. I have debugged with GDB using hardware watch points to determine that the reference to these shaders (among other variables throughout the program) changes upon entering these functions.
Thread 1 hit Hardware watchpoint 4: app->objects->render_object->vertex_shader
Old value = (VkShaderModule) 0x731f0f000000000a
New value = (VkShaderModule) 0x40d625 <glfwPollEvents+43>
_glfwPlatformPollEvents () at C:/Users/dylanweber/Documents/C-Projects/vlkengine/main/glfw/src/win32_window.c:1878
1878 {
This happens consistently but the variable changes to different values when I run it. Memory analysis tools like Dr. Memory (since I'm using Windows I cannot use Valgrind) only show memory problems in system DLLs (like xinput reading for controller inputs through GLFW) and are unrelated to my program. What could be the cause of this corruption? What tools/resources can I use to find these issues?
According to the code, the objectlink_add function accepts the second argument as a pointer. The most likely use of this is to add the pointer to an underlying data struct and keep it around for further references. A render pipeline was mentioned in the post, which wold be a sort of link.
However, the function was called from the application_init procedure which has the object triangle allocated on its stack. By the time the function is returned, its stack is gone and the value at the pointer becomes invalid.
There are several ways to fix it:
To allocate the triangle struct dynamically, using malloc (or similar). Therefore it will no disappear after the return from the function. This is the most generic way, but it calling to the free() function at some time is expected.
The triangle object could be static.
the objectlink_add could copy triangle fields in some internal struct, however, if there are multiple types of the objects, it cold be problematic.

Raising RAM in load BMP function SDL

I'm using SDL to code a simple game, and i have a big problem - i'm trying to do some animations with function,
in the fuction i call static int which keeps raising every game tick, and dependant on value of static int i change my variable image (with image=SDL_LoadBMP(myfile)), it's working great, but after 10 minutes of running a program, which had been working with 50MB of memory before without this really simple animation, ram usage of my program is starting to get bigger and bigger, and as i said, after 10 minutes it's 3GB and keeps raising every animation occur(so, like every 3 seconds).
Weird thing is also that i have other image which animation is a little bit simplier - i change my image upon clicking any arrow (still in main), and then call function, so after a second it gives back the initial image to a variable(it's giving image back in function), and it's working great - with that i mean - even if i keep clicking arrows, memory usage is constant.
my function looks like that:
void func(obj* image)
{
static int time1;
time1++;
if(time1>1000)
{
time1=0;
SDL_FreeSurface(image->image); //this doesn't change anything
image->image=SDL_LoadBMP("path");
}
else if(time1>800)
image->image=SDL_LoadBMP("path2");
else if(time1>600)
image->image=SDL_LoadBMP("path3");
else if(time1>400)
image->image=SDL_LoadBMP("path4");
}
typedef struct {
SDL_Surface* image;
}obj;
int main()
{
obj struct;
func(&struct);
}
ofc it's fulfilled with all this SDL library calls to make a window etc
https://i.ibb.co/YBcvjnF/Bez-tytu-u.png
If I understand correctly you're making SDL_Surface* over and over again, you never call SDL_FreeSurface()(info).
You need to load a some point all the BMP needed to play the animation into SDL_Surface* then reuse these BMP(s).
In your main (or into an init function) you need to store into an array or pointers the BMP images.
// Somewhere on one of your struct
SDL_Surface *animationImages[4];
// Then in an init function you do
animationImages[0] = SDL_LoadBMP("path");
animationImages[1] = SDL_LoadBMP("path2");
animationImages[2] = SDL_LoadBMP("path3");
animationImages[3] = SDL_LoadBMP("path4");
// And finally
void func(obj* image) {
static int time1;
time1++;
if (time1>1000) {
time1 = 0;
image->image = animationImages[0];
} else if (time1>800) {
image->image = animationImages[1];
} else if (time1>600) {
image->image = animationImages[2];
} else if (time1>400) {
image->image = animationImages[3];
}
}
And before the end of your game or when you don't need these animationImages anymore call SDL_FreeSurface() for each SDL_Surface* you have created.
// In a specific function used to clean up allocated stuff you do
SDL_FreeSurface(animationImages[0]);
SDL_FreeSurface(animationImages[1]);
SDL_FreeSurface(animationImages[2]);
SDL_FreeSurface(animationImages[3]);

How do I avoid circular dependancy coding UNDO/REDO in C?

//I'm moving this note to the top: I'm recreating OOP with structs and associated methods like int MyClass_getInt(MyClass* this)
I'm coding a small DAW in C. I have my Timeline and Region classes in Timeline.h. I would like my UndoRedoStack class to be able to work with multiple Timeline instances so I'd like the UndoRedoStack to be in a separate .c/.h file.
This line of thinking seems to require the TimelineUndoRedoCommand class to know about Timelines and Regions because it needs to backup pre-existing states.
It also requires Timelines to know about TimelineUndoRedoCommands so that it can fire them into the UndoRedoStack.
This seems to be a circular dependency. How should I structure this so that I can avoid circular dependencies?
//
I ended up asking Timeline.h to write all the code that needs it but house the UndoRedo separately like so:
/*
UndoRedoCmd
*/
typedef struct _UndoRedoCmd{
void* content;
char* name;
}UndoRedoCmd;
/*
UndoRedoStack
*/
typedef struct _UndoRedoStack{
t_LinkList* undoStack;
t_LinkList* redoStack;
bool redoingNow;
void (*redoFunc)(UndoRedoCmd* redoThis);
void (*undoFunc)(UndoRedoCmd* undoThis);
}UndoRedoStack;
/*
UndoRedoCmd
*/
UndoRedoCmd* UndoRedoCmd_New(char* name, void* content){
UndoRedoCmd* this = malloc(sizeof(UndoRedoCmd));
this->name=name;
this->content=content;
return this;
}
void UndoRedoCmd_Kill(UndoRedoCmd* this){
/*this should never be used. instead the
user of UndoRedoStack should provide
a custom killer which simply calls
free after freeing the contents
*/
}
/*
UndoRedoStack
*/
UndoRedoStack* UndoRedoStack_New(
void (*redoFunc)(UndoRedoCmd*),
void (*undoFunc)(UndoRedoCmd*),
void (*freeLinkFunction)(void*)
){
/*
redoFunc is meant to take the content of the command and redo some action with it.
undoFunc is the opposite
freeLinkFunction is meant should free a LinkList_Link with the custom UndoRedo content inside of it.
*/
UndoRedoStack* this = malloc(sizeof(UndoRedoStack));
this->undoFunc=undoFunc;
this->redoFunc=redoFunc;
this->redoStack = LinkList_New();
this->redoStack->autoFree=2;
this->redoStack->customFree=freeLinkFunction;
this->undoStack = LinkList_New();
this->undoStack->autoFree=2;
this->undoStack->customFree=freeLinkFunction;
return this;
}
void UndoRedoStack_Kill(UndoRedoStack* this){
LinkList_Free(this->undoStack);
LinkList_Free(this->redoStack);
free(this);
}
void UndoRedoStack_do(UndoRedoStack* this,char* name,void* undoredoinfo){
UndoRedoCmd* mycmd = UndoRedoCmd_New(name, undoredoinfo);
LinkList_push(this->undoStack, mycmd);
}
void UndoRedoStack_undo(UndoRedoStack* this){
if(this->undoStack->length==0){
return;
}
UndoRedoCmd* undoMe = (UndoRedoCmd*)LinkList_pop(this->undoStack);
this->undoFunc(undoMe);
LinkList_push(this->redoStack, undoMe);
}
void UndoRedoStack_redo(UndoRedoStack* this){
if(this->redoStack->length==0){
return;
}
UndoRedoCmd* redoMe = (UndoRedoCmd*)LinkList_pop(this->redoStack);
this->redoFunc(redoMe);
LinkList_push(this->undoStack, redoMe);
}

GtkSpinner with long-lasting function with C

I'm making a GTK+3 application in C and I want a spinner to show when the program is processing the data. Here's what I generally have:
main()
{
//Some statements
g_signal_connect(G_OBJECT(btnGenerate), "clicked", G_CALLBACK(Generate), &mainform);
}
void Generate(GtkWidget *btnGenerate, form_widgets *p_main_form)
{
gtk_spinner_start(GTK_SPINNER(p_main_form->spnProcessing));
Begin_Lengthy_Processing(Parameters, Galore, ...);
//gtk_spinner_stop(GTK_SPINNER(p_main_form->spnProcessing));
}
I have the stop function commented out so I can see the spinner spin even after the function has finished, but the spinner starts after the function is finished, and I suspect it turns on in the main loop.
I also found out that the entire interface freezes during the execution of the long going function.
Is there a way to get it to start and display inside the callback function? I found the same question, but it uses Python and threads. This is C, not Python, so I would assume things are different.
You need to run your lengthy computation in a separate thread, or break it up into chunks and run each of them separately as idle callbacks in the main thread.
If your lengthy computation takes a single set of inputs and doesn’t need any more inputs until it’s finished, then you should construct it as a GTask and use g_task_run_in_thread() to start the task. Its result will be delivered back to the main thread via the GTask’s GAsyncReadyCallback. There’s an example here.
If it takes more input as it progresses, you probably want to use a GAsyncQueue to feed it more inputs, and a GThreadPool to provide the threads (amortising the cost of creating threads over multiple calls to the lengthy function, and protecting against denial of service).
The GNOME developer docs give an overview of how to do threading.
This is what I got:
int main()
{
// Statements...
g_signal_connect(G_OBJECT(btnGenerate), "clicked", G_CALLBACK(Process), &mainform);
// More statements...
}
void Process(GtkWidget *btnGenerate, form_widgets *p_main_form)
{
GError *processing_error;
GThread *start_processing;
gtk_spinner_start(GTK_SPINNER(p_main_form->spnProcessing));
active = true;
if((start_processing = g_thread_try_new(NULL, (GThreadFunc)Generate, p_main_form, &processing_error)) == NULL)
{
printf("%s\n", processing_error->message);
printf("Error, cannot create thread!?!?\n\n");
exit(processing_error->code);
}
}
void Generate(form_widgets *p_main_form)
{
// Long process
active = false;
}
My program, once cleaned up and finished, as there are many other bugs in the program, will be put on GitHub.
Thank you all for your help. This answer comes from looking at all of your answers and comments as well as reading some more documentation, but mostly your comments and answers.
I did something similar in my gtk3 program. It's not that difficult. Here's how I would go about it.
/**
g_idle_add_full() expects a pointer to a function with the signature below:
(*GSourceFunc) (gpointer user_data).
So your function signature must adhere to that in order to be called.
But you might want to pass variables to the function.
If you don't want to have the variables in the global scope
then you can do this:
typedef struct myDataType {
char* name;
int age;
} myDataType;
myDataType person = {"Max", 25};
then when calling g_idle_add_full() you do it this way:
g_idle_add_full(G_PRIORITY_HIGH_IDLE, myFunction, person, NULL);
*/
int main()
{
// Assumming there exist a pointer called data
g_idle_add_full(G_PRIORITY_HIGH_IDLE, lengthyProcessCallBack, data, NULL);
// GTK & GDK event loop continues and window should be responsive while function runs in background
}
gboolean lengthyProcessCallBack(gpointer data)
{
myDataType person = (myDataType) *data;
// Doing lenghthy stuff
while(;;) {
sleep(3600); // hypothetical long process :D
}
return FALSE; // removed from event sources and won't be called again.
}

Dialog creation and destruction loop increases memory usage

I wrote a simple program module to ask a user for a profile name. To do that I create windoww with entry widget, and two buttons (Ok and Cancel) organized in a grid. When user enters a profile name that already exists it informs him of that fact by creating dialog with "ok" button, and after he presses it, it goes back to picking a profile name (the window was not hidden nor destroyed in the meantime). The problem is that when I create a profile, and then spam the ok button (by placing something heavy on enter key and going to make tea) on both profile name chooser and the dialog (making a simple loop with creation and destruction of a dialog) the memory usage of the program increases.
TL;DR
Simply creating and destroying gtk window (and dialog) seems to cause a memory leak. Leaving app in a loop made it increase it's memory usage by ~1900% (from 10mb to 200mb).
No, I didn't test for memory leaks using apps designed for it.
Yes, I've set G_SLICE=always-malloc.
Yes, there is another thread running in the background of the program (but I'm sure it doesn't cause any leaks)
I can post screens from Windows Performance Monitor if you want more info on what happens in the memory.
The question is - is it a memory leak caused by me, or is it GTK's fault (I heard it has a lazy policy of memory management, but after some time memory usage drops from 200mb to 140mb and stays there)?
Here's the code:
// This callback racts to the ok and cancel buttons. If input was correcs
// or the user pressed cancel it destroys the window. Else it show error
// prompt. The showing error prompt seems to be the problem here.
void pickNameButtCB(GtkWidget *button, gpointer *call)
{
GtkWidget *window = gtk_widget_get_toplevel(button);
if( *((char*)call) == 'k')
{
GList *entryBase = gtk_container_get_children(GTK_CONTAINER(gtk_bin_get_child(GTK_BIN(window)))), *entry = entryBase;
for(size_t i=g_list_length(entry); i>0 && !GTK_IS_ENTRY(entry->data); --i)
entry = g_list_next(entry);
if(gtk_entry_get_text_length(GTK_ENTRY(entry->data)) > 0)
{
const char *temp = gtk_entry_get_text(GTK_ENTRY(entry->data));
char path[266];
strcpy(path, settingsDir);
strcat(path, temp);
strcat(path, ".prof");
if(settProfExists(path))
{
g_list_free(entryBase);
showError(GTK_WINDOW(window), GTK_MESSAGE_ERROR, "Profile with that name already exists!");
return;
}
// nothing here executes as well
}
else
{
/** doesn't execute when the memory leak happens */
}
g_list_free(entryBase);
}
gtk_widget_destroy(window);
gtk_main_quit();
}
void showError(GtkWindow *parent, GtkMessageType type, const char *str)
{
GtkWidget *window = gtk_message_dialog_new(parent, GTK_DIALOG_DESTROY_WITH_PARENT, type, GTK_BUTTONS_OK, str);
g_signal_connect_swapped(window, "response", G_CALLBACK(gtk_widget_destroy), window);
gtk_dialog_run(GTK_DIALOG(window));
}
bool settProfExists(const char *path)
{
if(fileExists(path))
return true;
return false;
}
bool fileExists(const char *path)
{
struct stat info;
errno = 0;
if((stat(path, &info)) != 0)
if(errno == ENOENT)
return false;
return true;
}
Your code is too incomplete to find the root cause.
This line especially is doesn't make sense. We're missing the definition of entry and you're trying to do several operations on the same line (*entry = entryBase;).
GList *entryBase = gtk_container_get_children(GTK_CONTAINER(gtk_bin_get_child(GTK_BIN(window)))), *entry = entryBase;
The leak may however be in functions you call for which you don't provide the code (settProfExists, newProfile). So please provide a minimal compilable example that reproduces the problem.
As for the style, there are several errors: you're traversing a list the way you'd do with an array. See how is implemented GList and you'll see that this is silly (hint: look at entry->prev and entry->next):
for(size_t i=g_list_length(entry); i>0 && !GTK_IS_ENTRY(entry->data); --i)
entry = g_list_next(entry);
Then an architectural problem: don't try to inspect your UI to guess where are the widgets, just create a structure, and pass you call parameter and the GtkEntry you're interested in, in a structure with the gpointer data argument of the callback.
You should also not make paths by hand: you're using a fixed length array that may not be long enough. Use the portable g_build_path provided by the GLib (and free the path with g_free after use), that will handle for you Windows/Linux directories separators.
For your dialog, as you run gtk_run_dialog, you may just directly call gtk_destroy_widget afterwards instead of connecting a signal:
GtkWidget *window = gtk_message_dialog_new(parent, GTK_DIALOG_DESTROY_WITH_PARENT, type, GTK_BUTTONS_OK, str);
gtk_dialog_run(GTK_DIALOG(window));
gtk_widget_destroy(window);

Resources