While I was working on the next release of Mental Math CE, some of the code that I added made CEmu crash completely. Resetting the calculator did nothing, but when I reset CEmu, it began working again.

The code that I added between the last successful run was the following code in problem_sets.h:

Code:
if (exercise.type == COMPLEMENTS) {
      
      width = 220;
      height = 80;
      
      dialog((320 - width) / 2, (240 - height) / 2, width, height);
      draw_input_box_centered("Complements of", (240 - height) / 2 + 20);
      draw_input_box_centered("# of problems:", (240 - height) / 2 + 45);
      gfx_BlitBuffer();
      
      // Get upper bound (5 digits)
      upper_bound_str = malloc(6);
      memset(upper_bound_str, '\0', 6);
      input_config.curr_char = upper_bound_str;
      input_config.visible_buffer = upper_bound_str;
      
      do {
         do {
            key = textio_NumericalInput(upper_bound_str, 5, 46, 188, 107);
            gfx_BlitRectangle(1, 188, 107, 46, 11);
         } while (key != sk_Enter && key != sk_Yequ && key != sk_Graph);
         
         if (key == sk_Yequ) {
            free(upper_bound_str);
            goto EXIT_MENU;
         };
         
      } while (atoi((const char*)upper_bound_str) == 0);
      
      exercise.upper_bound_1 = atoi((const char*)upper_bound_str);
      free(upper_bound_str);
      
      // Get number of problems (2 digits)
      num_problems_str = malloc(3);
      memset(num_problems_str, '\0', 3);
      input_config.curr_char = num_problems_str;
      input_config.visible_buffer = num_problems_str;
      
      do {
         do {
            key = textio_NumericalInput(num_problems_str, 2, 46, 185, 132);
            gfx_BlitRectangle(1, 185, 132, 46, 11);
         } while (key != sk_Enter && key != sk_Yequ && key != sk_Graph);
         
         if (key == sk_Yequ) {
            free(num_problems_str);
            goto EXIT_MENU;
         };
      
      } while (atoi((const char*)num_problems_str) == 0);
      
      exercise.num_problems = atoi((const char*)num_problems_str);
      free(num_problems_str);
      
      
      // For this exercise, the range is from the entered number (upper_bound_1) to zero.
      exercise.lower_bound_1 = 0;
   };


A screenshot of the CEmu console after the crash (the debugging output above the red error code is in input.c):



Could one of the developers tell me what is wrong?
Hint: Possibly a null pointer dereference. It says so in the console.

Edit: also that is some of the weirdest looking code I have ever seen. Why are you mallocing so much?
MateoConLechuga wrote:
Hint: Possibly a null pointer dereference. It says so in the console.


Ok, I will find the null pointer dereference. What threw me off was the CEmu error in red. I had not seen that happen before, and because I thought that the code worked, I figured that something had gone wrong with CEmu.

MateoConLechuga wrote:
Edit: also that is some of the weirdest looking code I have ever seen. Why are you mallocing so much?


Yes, it is weird Rolling Eyes The mallocs create the input buffers that the input routine uses. I have been having a difficult time avoiding compiler warnings with the malloc(), so I came up with less-than-optimal solution to get rid of them. I definitely need to replace all of that with something better.

Edit: I found where I had made my mistake: calling the input routine before setting up the cursor dimensions. All's well now!
Since upper_bound_str and num_problems_str are never in use at the same time, there is no need to make them different variables. Furthermore, since they're small and freed immediately after use, you should just declare them as local variables.
Code:
char inputBuffer[16];
. . .
memset(&inputBuffer, '\0', 6);
input_config.curr_char = &inputBuffer;
input_config.visible_buffer = &inputBuffer;
/* Get stuff */
. . .
memset(&inputBuffer, '\0', 3);
input_config.curr_char = &inputBuffer;
/* Get other, more different stuff */
As long as the size of all arguments (char and short both get expanded to 3 bytes when passed as arguments, FYI) and local variables does not exceed 120ish bytes, it'll be fine. The win here is that by having the buffer be a fixed-size local, you eliminate any potential memory leak.
Thanks for the tip, DrDnar! I removed all of the redundant input code in the special_ops_pset function and created a single function that did all of the mallocating and getting input internally. I applied what you said about creating a local char array and it cut several bytes off the routine. I am also glad to get rid of a potential memory leak, given the plethora of ways those can be exploited. Wink

Code:
 // Returns number if enter pressed; returns -1 if Yequ pressed; returns -2 if Graph pressed
static int numerical_input(uint8_t magnitude, uint24_t xPos, uint8_t yPos, bool Yequ_esc, bool Graph_esc) {
   
   int number;
   kb_key_t key;
   
   char buffer[6] = {'\0'};
   
   number = 0;

   input_config.curr_char = &buffer;
   input_config.visible_buffer = &buffer;

   do {
      for (;;) {
         key = textio_NumericalInput(&buffer, magnitude, 46, xPos, yPos);
         gfx_BlitRectangle(1, xPos, yPos, 46, 11);

         if ((key == sk_Yequ && Yequ_esc) || (key == sk_Graph && Graph_esc) || (key == sk_Enter))
            break;
      };
      
      if (key == sk_Yequ && Yequ_esc) {
         number = -1;
         break;
      };
      
      // Start exercise if and only if Graph key is active and the num_problems is greater than 0
      if ((key == sk_Graph && Graph_esc) && atoi((const char*)buffer) > 0) {
         number = -2;
         break;
      }
      
   } while (atoi((const char*)buffer) == 0);
   
   if (key != sk_Yequ && key != sk_Graph)
      number = atoi((const char*)buffer);
   return number;
}
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are GMT - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement