开发者

Segmentation fault on the server, but not local machine

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 cha开发者_如何学运维r)+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.


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.)


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.


I just ran into this problem with godaddy and found that the FTP client was uploading in ASCII and not Binary. I changed the extension to .bin before uploading and it works normally now.


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.


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.


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.


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.


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.


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;
}


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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜