views:

300

answers:

11

As stated in the title, the program is working on my local machine (ubuntu 9.10) but not on the server (linux). It's a grid hosting hosting package of godaddy.

Please help..

Here is the code:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    long offset;
    FILE *io;
    unsigned char found;
    unsigned long loc;

    if (argc != 2)
    {
        printf("syntax: find 0000000\n");
        return 255;
    }

    offset = atol(argv[1]) * (sizeof(unsigned char)+sizeof(unsigned long));

    io = fopen("index.dat","rb");
    fseek(io,offset,SEEK_SET);
    fread(&found,sizeof(unsigned char),1,io);
    fread(&loc,sizeof(unsigned long),1,io);

    if (found == 1)
        printf("%d\n",loc);
    else
        printf("-1\n");

    fclose(io);

    return 0;
}

EDIT: It's not my program. I wish I knew enough C in order to fix it, but I'm on a deadline. This program is meant to find the first occurrence of a 7 digit number in the PI sequence, index.dat contains an huge array number => position.

http://jclement.ca/fun/pi/search.cgi

EDIT 2: I've used the updated code with the test for null pointer, still getting the same results. The program is working fine on my local machine, this error only happens on the server.

A: 

Maybe you should try and allocate some memory for found and loc variables ?

hyperboreean
found and loc are on the stack.
Wade Williams
A: 

First, you've given us no context on where the error occurs.

Second, before people spend time on it you need to add error checking.

Wade Williams
This isn't an answer. It's a comment.
Jefromi
Specifically, check that the file was actually opened, and perhaps that it is long enough. Maybe print out that offset to determine it is what you expect it to be.
kwatford
+5  A: 

The most likely thing is that the fopen is failing - you're not checking its return value to see if you actually got a valid pointer. (You get a segfault when you try to use that NULL pointer in the next line.)

Jefromi
if (io==NULL) {fputs ("File error",stderr); exit (1);}
I've added error checking for the null pointer with the same results.
Menachem Almog
A: 

Maybe "index.dat" isn't on your server but is on your machine. Since you're opening it with "rb" and not checking io after the fopen that could very well do it.

Chris
Or perhaps your local machine is case-insensitive and the file is named Index.dat.
Wade Williams
I've uploaded the entire directory as is.
Menachem Almog
@Wade: The local machine is Ubuntu, which is a Linux distro, and hence the file names are case-sensitive.
David Thornley
@David - whoops my bad. I misread it and thought Ubuntu was the server.
Wade Williams
+1  A: 

My initial guess is that the file failed to open, and thus io is NULL.

But Wade is right: you should add some error handling to your program first - at minimum that will give you (and us) a better idea of what is going wrong.

Lars
+2  A: 

Updated Source Code

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)

{
    long offset;
    FILE *io;
    unsigned char found;
    unsigned long loc;

printf( "A\n" );

if (argc != 2)
{
    printf("syntax: find 0000000\n");
    return 255;
}

printf( "B\n" );

offset = atol(argv[1]) * (sizeof(unsigned char)+sizeof(unsigned long));

printf( "C\n" );

/* Quick fix to check if the file exists to avoid a possible segfault. */
if( (io = fopen("index.dat","rb")) == NULL ) {
  printf( "Could not open index.dat.\n" );
  return -1;
}

printf( "D\n" );

fseek(io,offset,SEEK_SET);
fread(&found,sizeof(unsigned char),1,io);
fread(&loc,sizeof(unsigned long),1,io);

printf( "E\n" );

if (found == 1)
    printf("%d\n",loc);
else
    printf("-1\n");
fclose(io);

printf( "G\n" );

return 0;
}

Expected Results

It will now print an error if index.dat does not exist.

Preconditions

You will have to make sure the program exists in the same directory as index.dat.

Do not name the program find; name it scan, findindex, or similar. There already exists a program named find most UNIX systems (such as Linux).

Other Answers

The poster mentioned having little knowledge of C programming, so posting the fixes you have presented within context of the entire program would probably be more helpful. Stating answers like, "You have to check for null" without showing example code in context, while helpful to an experienced programmer, is likely not helpful to a new or non-programmer. That devil always finds its way into the details.

Update

Added debugging. See Alok's answer for the ideal approach to finding the problem with the code.

Dave Jarvis
Thanks for taking the time.I still get "Segmentation fault", with the updated code.
Menachem Almog
Try adding debugging, as I have shown above. What letters do you see? This is a fairly primitive technique to isolate problems: just print out a sequence between code blocks that you think are failing. In this case, since I do not want to presume I know where the problem exists, the debugging will pin-point the problem area.
Dave Jarvis
I've done that and still and I get the "Segmentation fault" even when I printf before the "long offset"
Menachem Almog
A: 

Change the middle section of your code to:

fseek(io,offset,SEEK_SET);
printf("fseek worked\n");
fread(&found,sizeof(unsigned char),1,io);
printf("fread 1 worked\n");
fread(&loc,sizeof(unsigned long),1,io);
printf("fread 2 worked\n");

and see which lines get printed when you run the program. That should give you a hint as to where exactly the problem is.

Edit: When I say a function call "worked", I mean "didn't cause a segfault". Ideally you would want to check each call to fseek and fread to make sure they didn't encounter any errors, but you mentioned you were on a deadline so this is just some quick-n-dirty error tracing to try and track down the segfault.

bta
I wouldn't say that successfully reaching the next line indicates that fseek or fread "worked" - you need to check the return value to determine that.
Andrew Medico
`fseek` returns `-1` in the case of failure.
Alok
@Andrew,Alok: True. I was writing this as something that was easy to add and understand for someone not familiar with the C language (as the OP admitted). I agree that the return from `fseek` should be checked and the code should verify that there is enough file left to `fread` after the `fseek`, but I was trying to keep it simple for a novice on a deadline. And by "worked", I mean "didn't cause a segfault".
bta
A: 

Can you run gdb on the server? If so, build with debugging enabled (-g option to gcc) and run it in gdb. That will tell you where the program is failing. Here's how (replace the stuff in <> with the relevant info):

# gdb <program>

(gdb) set args <arg>
(gdb) run

gdb will catch the segfault and show the line where it crashed.

JayM
Newbie programmer. Alok's answer is probably the most correct here.
Dave Jarvis
I can't run gdb on the server.
Menachem Almog
+1  A: 

My guess would be that sizeof(long) on the server is 8 (due to it being a 64-bit system), vs. 4 on your local machine (assuming a 32-bit machine). Thus your calculated offset into the file would be wrong by a factor of 2. If you need to go to a specific offset in the file, you should be using fixed-size types - i.e. uint32_t and the like.

Andrew Medico
+2  A: 

Maybe the sizes of unsigned long are not the same on the machines.

What does the following program print on your machines?

#include <stdio.h>

int main(void)
{
    printf("%zu\n", sizeof(unsigned long));
    return 0;
}

Compile with gcc -std=c99 file.c. If the sizes printed are indeed different, then you need to replace unsigned long by uint32_t, and add #include <inttypes.h> at the beginning of your program:

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdint.h>

int main(int argc, char **argv)

{
    long offset;
    FILE *io;
    unsigned char found;
    uint32_t loc;

    if (argc != 2)
    {
        printf("syntax: find 0000000\n");
        return 255;
    }
    /* sizeof(unsigned char) is 1, and I am assuming you wanted
       sizeof(unsigned long) to be 4.  But see below. */
    offset = strtol(argv[1], NULL, 0) * (1+4);

    if ((io = fopen("index.dat", "rb")) == NULL) {
        fprintf(stderr, "Cannot open file\n");
        return EXIT_FAILURE;
    }
    if (fseek(io, offset, SEEK_SET) == -1) {
        fprintf(stderr, "Error seeking\n");
        perror(NULL);
        return EXIT_FAILURE;
    }
    if (fread(&found, 1, 1, io) != 1) {
        fprintf(stderr, "Error in first fread\n");
        return EXIT_FAILURE;
    }
    /* using sizeof loc makes sure that the correct size if always used,
       irrespective of the type of loc */
    if (fread(&loc, sizeof loc, 1, io) != 1) {
        fprintf(stderr, "Error in second fread\n");
        return EXIT_FAILURE;
    }
    if (found == 1)
        printf("%" PRIu32 "\n", loc);
    else
        printf("-1\n");
    fclose(io);

    return 0;
}

The above assumes that the "correctly working" program has 4 byte unsigned long. If not, you will need to replace the 4 in the program with whatever the size of unsigned long on the correct computer is.

If this is the reason of the difference, then you now know one of the problems with reading and writing binary data: you have to be very careful about sizes, endianness, etc.

Alok
This is even better than the quick debugging I recommended. This is the correct way to resolve the issue. No guessing and it improves the software.
Dave Jarvis
I've tried compiling the file.c code, but it didn't compile for some reason. Anyway I've compiled the revised code and I get the same results: it's working on my local machine but "Segmentation fault" on the server.
Menachem Almog
@menachem-almog: did you compile with `gcc -std=c99`?
Alok
@Alok: He says it segfaults before the "long offset" declaration. My first thought was that there could be hardware differences between the server and workstation.
Dave Jarvis
@Alok: yes I did.
Menachem Almog
@menachem-almog: what was the error?
Alok
@Alok: Which error? the file.c compiling?
Menachem Almog
@menachem-almog: Yes.
Alok
@Alok: I've tried again and it did compiled. When I ran it on my local it returns 4, and on the server (not surprisingly) "Segmentation fault". I'm ready to jump out the window :(
Menachem Almog
@menachem-almog: that simple program gave you segmentation fault on the server? There is something seriously wrong on your server then.
Alok
@Alok: yeah I figured I'm gonna go yell on them till I get this to work. "Serious fun" with godaddy..
Menachem Almog
@menachem-almog: Maybe they have some restrictions on what you can do. But it doesn't make any sense. Can you run a "hello world" program on the server? Good luck.
Alok
@menachem-almog: are you compiling the program that runs on the server on the server? You aren't copying the program over from the workstation, right?
Fred
@Fred: good point.
Alok
A: 

I think you are reading outside the file limits. I added a portion to check the file size and ensure you are reading within the file limits.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    long offset;
    FILE *io;
    unsigned char found;
    unsigned long loc;

    if (argc != 2)
    {
        printf("syntax: find 0000000\n");
        return 255;
    }

    offset = atol(argv[1]) * (sizeof(unsigned char)+sizeof(unsigned long));

    io = fopen("index.dat","rb");
if (io==NULL) {fputs ("File error",stdout); exit (1);}
fseek (io , 0 , SEEK_END);
long fileSize = ftell (io);
long offsetEnd = offset+sizeof(unsigned char)+sizeof(unsigned long);
printf("file size: %d\nseek: %d\nseekEnd: %d\n",fileSize,offset,offsetEnd);

if (offsetEnd> fileSize) {fputs ("Reading outside of file...",stdout); exit (1);}

    fseek(io,offset,SEEK_SET);
    fread(&found,sizeof(unsigned char),1,io);
    fread(&loc,sizeof(unsigned long),1,io);

    if (found == 1)
        printf("%d\n",loc);
    else
        printf("-1\n");

    fclose(io);

    return 0;
}