Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

Tuesday, February 12, 2013

HOWTO Make a Quick and Dirty (Pseudo)Random Number Generator

If you ever need to build your own quick and dirty (pseudo-)random number generator it actually isn't that hard. This generator is used in various real-world systems:
  • Visual Basic (to version 6)
  • A few ANSI C implementations, including glibc
  • Java's Random library
The implementation will iterate over all numbers [0,m) when using proper a, m ,c's. 1

Implementation

#include <stdio.h>
#include <unistd.h>

const long m = 4294967296; // 2 ^ 32
const long a = 1103515245;
const long c = 12345;

long lastX = 0;

long nrandom() {
lastX = (a * lastX + c) % m;
return lastX;
}

void seed(int num)
{
lastX = num;
}

int main()
{
int i;

seed(getpid());

for(i = 0; i < 1000; i++)
printf("%li\n", nrandom());
}
Note that this implementation only generates m pseudorandom numbers, in this case 4,294,967,296; so if you need more, you'll want to use a different algorithm.

  1. These conditions require some discrete mathematics that are too long to go in to here; it involves coprime numbers and recurrence relations. (Please point out if I've missed some simple explaination in the comments, I'm fairly new to this!)

Wednesday, January 30, 2013

HOWTO Debug Crashes in C/C++ Applications on Ubuntu

In this howto we'll cover:
  • Compiling C/C++ code for debugging
  • Allowing debugging
  • Viewing errors
  • Fixing common gdb issues
Your computer is happily humming along and your program is progressing fine, suddenly disaster strikes! Segmentation fault (core dumped) your computer yells before it plunges back to darkness and your friendly shell prompt reappears.

The way of debugging in Ubuntu when coding by hand is not nearly as nice as popping up an IDE, but when done right can be much faster.

Our Problematic Code

For demonstration we'll be using this bit of code that is written to cause crashes.
int main()
{
int* p = 0x0000007b; // The cause of many a Windows XP BSOD
int j;

for(j = 0; j < 10000000; j++)
{
p++;
*p = j;
}

return 1;
}
In order to get the best debugging results you'll have to compile your code with the -ggdb flag, in this instance: gcc -ggdb killer.c.
If you run this program, it will die nearly right away with the error: Segmentation fault (core dumped).

The -ggdb flag to the compiler instructs it to include lots of debugging information. However, you won't want this on production executables because it takes up a lot of space. This example program was 9.6K with symbols, and 6.2K without!

Enabling the Dump

By default, Ubuntu 12.10 won't output crash information for programs you make yourself, to fix this you'll need to run the command:
ulimit -c unlimited
This will need to be run every time you log back on to your system.

Debugging

Once you have logging enabled and your program crashes a file called core should appear in the directory from which you ran the program. Use the gdb command to see what information it contains about the crash.
gdb a.out core
Where a.out is the name of your program that crashed and created the core file.

Analyzing the Debug Output

GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/joseph/Desktop/a.out...done.

[New LWP 13663]

warning: Can't read pathname for load map: Input/output error.
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004004ed in main () at breakme.c:9
9 *p = j;
This is the output you'll get from the gdb command, all you want is the last three lines, from the top they tell you:
  1. What happened.
  2. Where the error happened (in main in file breakme.c on line 9)
  3. What the line was.

Common gdb Errors

  • warning: exec file is newer than core file. means the core file you're using wasn't made by your executable, you'll need to delete it and run your program again.
  • warning: core file may not match specified executable file. means the core file you're running against probably wasn't made by the program you specified, gdb will probably report wrong results.

Saturday, December 17, 2011

Watching A Directory For Changes

This is a very simple VALA script that watches a directory for changes (not including sub-directories) then prints out the changed files.

Usage: changewatch /path/to/folder/to/watch


/**
* Watches a directory for changes:
*
* compile: valac changeWatch.vala --pkg gio-2.0
* Copyright 2011-12-09 Joseph Lewis
* Apache License
*/

using GLib;

void on_change (File f) {
print(f.get_path() + "\n");
}

void main (string[] argv) {

if(argv[1] == null)
{
print("Usage: "+argv[0]+" /path/to/file/to/watch\n");
return;
}

GLib.File fp = File.new_for_path(argv[1]);

GLib.FileMonitor mon1;

try {
mon1 = fp.monitor_directory(
GLib.FileMonitorFlags.NONE
);
mon1.changed.connect(on_change);
print("Monitoring: "+fp.get_path()+"\n");
} catch (GLib.Error e) {
print("Error: "+e.message+"\n");
}
GLib.MainLoop loop = new GLib.MainLoop();
loop.run();
}

Saturday, December 11, 2010

Protocols #1, Echo Protocol

Today I set off on a mission to implement every major protocol of the Internet.  I will start with the echo protocol in C.



Code:
/* Copyright 2010 Joseph Lewis <joehms22@gmail.com>
* GNU GPL v 3.0
*
* TO COMPILE:
* cc -lpthread echo.c
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <arpa inet.h>
#include <sys types.h>
#include <netinet in.h>
#include <sys socket.h>

void *print_message_function( void *ptr );
void *tcp_server( void *ptr );
void *udp_server( void *ptr );

void error(char *msg)
{
perror(msg);
exit(1);
}

/*Compares two strings for equality*/
int compare(char one[], char two[])
{
int j = strncmp(one, two, 100);
return (j == 0);
}

/*Show the help menu with the given program path.*/
void show_help(char name[])
{
printf( "\n" );
printf( "Usage: %s [-t][-u] [-p portumber] \n", name);
printf( "Starts a RFC 862 compliant echo server.\n");
printf( " -t Start on TCP\n");
printf( " -u Start on UDP\n");
printf( " -p Start on port (number) Default: 7\n");
printf( " -? Show this menu\n");
printf( "Example:\n");
printf( " %s -t -u -p 7\n", name);
printf( "\n" );
exit(1);
}

//Globals
int tcp = 0;
int udp = 0;
int portnumber = 7;

int main ( int argc, char *argv[] )
{
/*Parse command line arguments*/

if ( argc != 1 ) /* If there are arguments parse them. */
{
int loc = 1; /* argv[0] should be program name */

while( loc < argc )
{
//Display the help menu
if( compare(argv[loc], "--help") ||
compare(argv[loc], "-?") ||
compare(argv[loc], "-h") )
{
show_help(argv[0]);
}

//The port number
if( compare(argv[loc], "-p") )
{
if( loc + 1 >= argc ) //Too few arguments, display help
{
argv[loc] = "--help";
} else {
portnumber = atoi( argv[loc+1] );
loc += 1;
}
}

if( compare(argv[loc], "-t") )
tcp = 1;

if( compare(argv[loc], "-u") )
udp = 1;

loc += 1;
}
}else{
show_help(argv[0]);
}


pthread_t thread1, thread2;
char *message1 = "Thread 1";

/* Create independent threads each of which will execute function */

pthread_create( &thread2, NULL, udp_server, (void*) message1);
pthread_create( &thread1, NULL, tcp_server, (void*) message1);


/* Wait untill threads are complete before main exits. */

pthread_join( thread1, NULL);
pthread_join( thread2, NULL);

exit(0);
}

void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}

void *tcp_server( void *ptr )
{
if(tcp)
{
printf("TCP started on port %i\n",portnumber);

int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");

bzero((char *) &serv_addr, sizeof(serv_addr));

portno = portnumber;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portnumber);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
while( 1 )
{
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
do
{
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
n = write(newsockfd,buffer,n);
if (n < 0) error("ERROR writing to socket");
}while( n > 0 );
}

}
}

void *udp_server( void *ptr )
{
if(udp)
{
printf("UDP started on port %i\n",portnumber);

int sock, length, fromlen, n;
struct sockaddr_in server;
struct sockaddr_in from;
char buf[1024];

sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
error("Problem opening socket");

length = sizeof(server);
bzero(&server,length);

server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(portnumber);

if (bind(sock,(struct sockaddr *)&server,length)<0)
error("Problem binding UDP");
fromlen = sizeof(struct sockaddr_in);

while( 1 )
{
n = recvfrom(sock,buf,1024,0,(struct sockaddr *)&from,&fromlen);
if (n < 0)
error("recvfrom");
n = sendto(sock,buf,n,0,(struct sockaddr *)&from,fromlen); //echo
if (n < 0)
error("sendto");
}
}
}