WTF, program segfaulting before even starting...

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Mortabis
Posts: 50
Joined: Fri Feb 08, 2008 12:24 am UTC

WTF, program segfaulting before even starting...

Postby Mortabis » Sat Apr 12, 2008 12:47 am UTC

For CS class, I had to make a program that would look like the opening animation from The Matrix, where the letters rain down the screen. I made a very accurate rendition of it in Java, but I wanted a terminal version of it. Here's the code, which segfaults before starting:

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define DURATION 500 //how long the pause lasts, not in any particular unit.
#define HEIGHT 76 //how high it is in the terminal
#define WIDTH 80 //how wide it is in the terminal

/* About this program:
 * This is a simple in-console rendition of the opening graphical trick in the movie "The Matrix",
 * wherein ASCII characters rain down the screen.  It's simplified, in that there are no "raindrops",
 * just a screenfull of falling characters, some of which are white and most of which are green.
 */
struct row {
   char col[WIDTH]; //characters in the row
   int y[WIDTH]; //sets color
}  *array[HEIGHT]; //pointers for easy swappy swappy; it's only used as a 1-d array

void newrow();
void printrows();
void swaprows();
void genarr();
void pause(long dur);

int main()
{
   printf("Starting program"); //tells us whether the bitch is segfaulting yet
   genarr(); //generate the initial array
   printf("Working so far..."); //same purpose as previous printf statement
   while(1)//infinite loop
   {
      printrows(); //display the "matrix"
      swaprows(); //move the "matrix"
      pause(DURATION); //make it not go faster than the screen's refresh rate >_<
   }//end loop
   return 0;
}//end main function

void printrows()//prints the rows into the terminal screen
{
   printf("\f"); //clear the terminal screen
   int i;
   int j;
   for(i=0; i<HEIGHT; i++)
   {
      for (j=0; j<WIDTH; j++)
      {
         if (!array[i]->y[j])
            printf("%c[7;31", array[i]->col[j]); //print our character white
         else
            printf("%c[2;31", array[i]->col[j]); //print our character green
         }//end inner loop
         printf("\n"); //print a newline
   }//end outer loop
}//end function
void swaprows() //swaps our rows so that it's not the same boring shit over and over
{
   int i;
   int j;
   /* There's no temp because we're actually replacing the lost row at the end */
   for (i=HEIGHT-1; i>0; i--)
   {
      array[i] = array[i-1];
   }//end for
   newrow(); //this generates a new row at the top
}//end function
void newrow() //make a new row so the old stuff doesn't get stale
{
   int i;
   for (i=0; i<WIDTH; i++)
   {
      array[0]->col[i] = (char) (rand() * 94 + 32); //set the character
      array[0]->y[i] = (int) (rand() * 5); //set the color
   }//end loop
}//end function
void genarr() //make the initial array
{
   int i;
   int j;
   printf("Starting genarr outer loop"); //I don't think i or j is causing a segfault, but nonetheless, we'll know now
   for (i=0; i<HEIGHT; i++)
   {
      for (j=0; j<WIDTH; j++)
      {
         array[i]->col[j] = (char) (rand() * 94 + 32); //set the character
         printf("%s %i", "Assigning column ", i);
         array[i]->y[j] = (int) (rand() * 5); //set the color
      }//end inner loop
   }//end outer loop
}//end function
void pause(long dur) //just does a bunch of slow calculations; will use time.h stuff later.
{
   double var;
   long i;
   for (i=0; i<dur; i++)
      var = rand(); //to take up time.
}//end function


I think it's segfaulting when it initializes the struct at the beginning. GCC doesn't return any warnings...at least not that I recall...
Image

User avatar
Bruce
Posts: 447
Joined: Tue Feb 12, 2008 11:44 am UTC
Location: Melbourne

Re: WTF, program segfaulting before even starting...

Postby Bruce » Sat Apr 12, 2008 12:49 am UTC

Off topic, but cmatrix and xmatrix already exist!

More on topic, without reading your code you may want to learn gdb. It will help you.
COMFORT, n.
A state of mind produced by contemplation of a neighbor's uneasiness.

Rysto
Posts: 1459
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: WTF, program segfaulting before even starting...

Postby Rysto » Sat Apr 12, 2008 12:51 am UTC

Replace all of the printfs with fprintf(stderr. printf is not guaranteed to get its output to the console before a crash.

User avatar
evilbeanfiend
Posts: 2650
Joined: Tue Mar 13, 2007 7:05 am UTC
Location: the old world

Re: WTF, program segfaulting before even starting...

Postby evilbeanfiend » Sat Apr 12, 2008 1:08 am UTC

or call fflush on stdout if you really need the output on stdout instead of stderr
in ur beanz makin u eveel

User avatar
Mortabis
Posts: 50
Joined: Fri Feb 08, 2008 12:24 am UTC

Re: WTF, program segfaulting before even starting...

Postby Mortabis » Sat Apr 12, 2008 1:19 am UTC

I sent the code to my friend, who ran it in gdb. Whenever I say "array[x]->col[y]" or something similar it segfaults. In fact it seems to segfault whenever I mention the variable "array" at all.

Now I know where it's segfaulting, but not why or how to fix it. So if someone here could look through the actual code and try to find the error, I'd appreciate it. I'm stumped.
Image

Rysto
Posts: 1459
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: WTF, program segfaulting before even starting...

Postby Rysto » Sat Apr 12, 2008 1:36 am UTC

Code: Select all

array[i]->col[j]

array[i] never gets initialized.

User avatar
Mortabis
Posts: 50
Joined: Fri Feb 08, 2008 12:24 am UTC

Re: WTF, program segfaulting before even starting...

Postby Mortabis » Sat Apr 12, 2008 1:53 am UTC

Okay I made it not a pointer and as it happens my swap still works. Now it runs.

But it doesn't print in color. So now I have a new problem: How do I make printf print in color?

I googled it and currently it uses what I found in the printf() calls in printrows(). And of course, that doesn't work...
Image

Rysto
Posts: 1459
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: WTF, program segfaulting before even starting...

Postby Rysto » Sat Apr 12, 2008 2:14 am UTC

There's no way to do that in standard C.

User avatar
notzeb
Without Warning
Posts: 629
Joined: Thu Mar 08, 2007 5:44 am UTC
Location: a series of tubes

Re: WTF, program segfaulting before even starting...

Postby notzeb » Sat Apr 12, 2008 2:16 am UTC

Curses!
Zµ«V­jÕ«ZµjÖ­Zµ«VµjÕ­ZµkV­ZÕ«VµjÖ­Zµ«V­jÕ«ZµjÖ­ZÕ«VµjÕ­ZµkV­ZÕ«VµjÖ­Zµ«V­jÕ«ZµjÖ­ZÕ«VµjÕ­ZµkV­ZÕ«ZµjÖ­Zµ«V­jÕ«ZµjÖ­ZÕ«VµjÕ­Z

User avatar
hotaru
Posts: 1040
Joined: Fri Apr 13, 2007 6:54 pm UTC

Re: WTF, program segfaulting before even starting...

Postby hotaru » Sat Apr 12, 2008 4:03 am UTC

notzeb wrote:Curses!

or ansi escape sequences...

Code: Select all

factorial product enumFromTo 1
isPrime n 
factorial (1) `mod== 1

User avatar
Bruce
Posts: 447
Joined: Tue Feb 12, 2008 11:44 am UTC
Location: Melbourne

Re: WTF, program segfaulting before even starting...

Postby Bruce » Sat Apr 12, 2008 4:20 am UTC

curses is the better way to do it, which is also a nice tool to have learnt.
COMFORT, n.
A state of mind produced by contemplation of a neighbor's uneasiness.

User avatar
Eschatokyrios
Posts: 244
Joined: Fri Dec 22, 2006 6:49 pm UTC

Re: WTF, program segfaulting before even starting...

Postby Eschatokyrios » Sat Apr 12, 2008 9:15 am UTC

I know far, far too little about C to be of any help, unfortunately.

That said, when you finally do get the program working, mayhap you'd like to release the source? It sounds damned cool and I'd love to have a copy for myself.
კაცი ბჭობდა, ღმერთი იცინოდაო
k'atsi bch'obda, ghmerti itsinodao
"Man was discussing, God was laughing"
-Georgian proverb

Dakman
Posts: 50
Joined: Sat Jul 07, 2007 7:49 am UTC

Re: WTF, program segfaulting before even starting...

Postby Dakman » Sat Apr 12, 2008 1:25 pm UTC

Curses is a little heavy for this I would thing. My rule is that unless the program is supposed to act like a GUI, I don't use it. You might want to check out...

http://www.databeast.com/datacomet/Docu ... nd_Set.txt

Great and easy to understand documentation. At any rate it looks like your just forgetting to put the closing character in your escape sequence.

printf("%c[2;31", array[i]->col[j]);

Should be...

printf("%c[2;31m", array[i]->col[j]);

Workaphobia
Posts: 121
Joined: Thu Jan 25, 2007 12:21 am UTC

Re: WTF, program segfaulting before even starting...

Postby Workaphobia » Sat Apr 12, 2008 9:32 pm UTC

Dakman wrote:Curses is a little heavy for this I would thing. My rule is that unless the program is supposed to act like a GUI, I don't use it. You might want to check out...

http://www.databeast.com/datacomet/Docu ... nd_Set.txt

Great and easy to understand documentation. At any rate it looks like your just forgetting to put the closing character in your escape sequence.

printf("%c[2;31", array[i]->col[j]);

Should be...

printf("%c[2;31m", array[i]->col[j]);

What? What happened to the escape character, \x1b or \033?
Evidently, the key to understanding recursion is to begin by understanding recursion.

The rest is easy.

User avatar
Bruce
Posts: 447
Joined: Tue Feb 12, 2008 11:44 am UTC
Location: Melbourne

Re: WTF, program segfaulting before even starting...

Postby Bruce » Sun Apr 13, 2008 12:12 am UTC

Eschatokyrios: cmatrix. Check it out.

Dakman: I completely disagree that curses is not appropriate. You want a persistent display with which you can update any part of the screen at any time. See also: cmatrix.

http://www.asty.org/cmatrix/
COMFORT, n.
A state of mind produced by contemplation of a neighbor's uneasiness.

User avatar
Mortabis
Posts: 50
Joined: Fri Feb 08, 2008 12:24 am UTC

Re: WTF, program segfaulting before even starting...

Postby Mortabis » Sun Apr 13, 2008 3:36 am UTC

Current source:

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#define DURATION 5000 //how long the pause lasts, not in any particular unit.
#define HEIGHT 60 //how high it is in the terminal
#define WIDTH 100 //how wide it is in the terminal

/* About this program:
 * This is a simple in-console rendition of the opening graphical trick in the move "The Matrix",
 * wherein ASCII characters rain down the screen.  It's simplified, in that there are no "raindrops",
 * just a screenfull of falling characters, some of which are white and most of which are green.
 */
struct row {
   char col[WIDTH]; //characters in the row
   int y[WIDTH]; //sets color
}  array[HEIGHT]; //pointers for easy swappy swappy; it's only used as a 1-d array

void newrow();
void printrows();
void swaprows();
void genarr();
void pause(long dur);

int main()
{
   printf("Starting program");
   genarr(); //generate the initial array
   printf("Working so far...");
   while(1)//infinite loop
   {
      printrows(); //display the "matrix"
      swaprows(); //move the "matrix"
      pause(DURATION); //make it not go faster than the screen's refresh rate >_<
   }//end loop
   return 0;
}//end main function

void printrows()//prints the rows into the terminal screen
{
   printf("\f"); //clear the terminal screen
   int i;
   int j;
   for(i=0; i<HEIGHT; i++)
   {
      for (j=0; j<WIDTH; j++)
      {
         if (!array[i].y[j])
            printf("%c",array[i].col[j]); //print our character white, assuming the same terminal settings as mine
         else
            printf("%c[1;32m", array[i].col[j]); //print our character green
         }//end inner loop
         printf("\n"); //print a newline
   }//end outer loop
}//end function
void swaprows() //swaps our rows so that it's not the same boring shit over and over
{
   int i;
   int j;
   /* There's no temp because we're actually replacing the lost row at the end */
   for (i=HEIGHT-1; i>0; i--)
   {
      array[i] = array[i-1];
   }//end for
   newrow(); //this generates a new row at the top
}//end function
void newrow() //make a new row so the old stuff doesn't get stale
{
   int i;
   for (i=0; i<WIDTH; i++)
   {
      array[0].col[i] = (char) (rand() * 89 + 33); //set the character
      array[0].y[i] = (int) (rand() * 5); //set the color
   }//end loop
}//end function
void genarr() //make the initial array
{
   int i;
   int j;
   printf("Starting genarr outer loop");
   for (i=0; i<HEIGHT; i++)
   {
      for (j=0; j<WIDTH; j++)
      {
         array[i].col[j] = (char) (rand() * 89 + 33); //set the character
         printf("%s %i", "Assigning column ", i);
         array[i].y[j] = (int) (rand() * 5); //set the color
      }//end inner loop
   }//end outer loop
}//end function
void pause(long dur) //just does really slow calculations to pause; will use time.h stuff later.
{
   double var;
   long i;
   long j;
   for (j=0; j<dur; j++)
   for (i=0; i<dur; i++)
      var = rand(); //to take up time.
}//end function


The pause is very erratic. I'll change that later. But more importantly, it's printing %c[1;32m ...I mean, it's green and all, but....is there any way to get rid of that? It sort of gets in the way.

But in any case, thanks for all the help so far. And Eschatokryios, yeah, check out cmatrix, I'm a newbie programmer too. :)
Image

zahlman
Posts: 638
Joined: Wed Jan 30, 2008 5:15 pm UTC

Re: WTF, program segfaulting before even starting...

Postby zahlman » Mon Apr 14, 2008 10:59 pm UTC

Mortabis wrote:Okay I made it not a pointer and as it happens my swap still works. Now it runs.


What you were trying to make was an array of pointers. But the pointers didn't actually point at anything. You have to make the pointer point at something before you can manipulate the pointed-at thing.

But there's actually no reason to swap things around. Instead, keep an index to the "current top row". Draw everything from that row to the end, and then from the beginning to just before that row. To move things down, decrement the current top (yes, decrease; think about what your frame of reference is), looping it around to the last row if you hit the beginning. Then initialize that top row.

Code: Select all

// Instead of picking obscure variable names and then explaining what they're for, just pick a variable name that says what it's for.
struct row {
   char symbols[WIDTH];
   int colour[WIDTH];
} screen[HEIGHT];
int current_top_row;

void printrows()
{
   // Exactly which language do you think you're using here? In strict C, you're not allowed to declare variables in the middle of
   // a scope, so you can't put the printf() call before 'int i' and 'int j'. In C++, you could declare 'i' and 'j' directly in the for-loop initializer.
   // Although in C++, you could do a lot of other things much more nicely too...
   printf("\f");
   int i;
   int j;
   for(i=0; i<HEIGHT; i++)
   {
      for (j=0; j<WIDTH; j++)
      {
         // Translate the 'i' value into a row index.
         int row = (i + current_top_row) % HEIGHT;
         if (!array[row].y[j]) {
            printf("%c[7;31", array[row].col[j]); // white
         } else {
            printf("%c[2;31", array[row].col[j]); // green
         }
      }
      printf("\n");
   }
}
// Don't put comments for obvious things. When you write a comment, you're drawing the code-reader's attention to the commented bit.
// If you keep making the reader look at ordinary things, s/he is either going to waste time, get confused, or start seeing you like the
// proverbial boy who cried wolf. Or a combination of those. Hint: "the reader" is often *you*. Don't annoy yourself.
// Also, if you keep consistent with indentation, and always brace your if/else logic, it should always be obvious what pairs with which.
// (Many text editors will do this for you, too. For example, in vim, position the cursor over a bracket and type '%'.)

void swaprows()
{
   int i;
   --current_top_row;
   if (current_top_row == -1) { current_top_row += HEIGHT; } // loop around.
   // No more swapping. Instead, we can pull the 'newrow' code directly in here, since we don't need it as a separate function.
   for (i=0; i<WIDTH; i++)
   {
      array[current_top_row].col[i] = (char) (rand() * 89 + 33);
      array[current_top_row].y[i] = (int) (rand() * 5); //<-- this DOES NOT DO what you think it does. rand() is not a coin flip, nor does
      // it pick values from 0 to 1, or anything interesting like that. C's rand() corresponds to Java's Random.nextInt() with no argument.
      // You need to do the logic yourself to map that into the range you want.
      // Similarly the character setting; your results will be effectively random over the entire range of characters.
      // What you probably want is rand() % <value>; note the use of the modulus (remainder after division) operator.
   }
}


But more importantly, it's printing %c[1;32m ...I mean, it's green and all, but....is there any way to get rid of that? It sort of gets in the way.


The text that you're supposed to output to change the ANSI colour codes is also supposed to have an 'escape' character in it - ascii character 27. What you want to do is print the whole escape sequence, and *then* the character: '\0x1b[1;32m%c' should do it.
Belial wrote:I once had a series of undocumented and nonstandardized subjective experiences that indicated that anecdotal data is biased and unreliable.

Dakman
Posts: 50
Joined: Sat Jul 07, 2007 7:49 am UTC

Re: WTF, program segfaulting before even starting...

Postby Dakman » Wed Apr 16, 2008 3:24 pm UTC

Bruce wrote:Eschatokyrios: cmatrix. Check it out.

Dakman: I completely disagree that curses is not appropriate. You want a persistent display with which you can update any part of the screen at any time. See also: cmatrix.

http://www.asty.org/cmatrix/


You can update any part of the screen at any time. Absolute and relative cursor positioning can be acheived without curses.

What? What happened to the escape character, \x1b or \033?


Srsly...


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 4 guests