服务器上出现分段错误,但本地计算机上没有分段错误

发布于 2024-08-24 14:02:04 字数 1053 浏览 4 评论 0原文

如标题所述,该程序可以在我的本地计算机(ubuntu 9.10)上运行,但不能在服务器(linux)上运行。这是godaddy的网格托管托管包。

请帮助..

这是代码:

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

编辑:这不是我的程序。 我希望我了解足够的 C 语言来修复它,但我已经到了最后期限。该程序的目的是查找 PI 序列中第一次出现的 7 位数字,index.dat 包含一个巨大的数组数字 =>位置。

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

编辑2:我已经使用更新的代码来测试空指针,仍然得到相同的结果。 该程序在我的本地计算机上运行良好,此错误仅发生在服务器上。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

向地狱狂奔 2024-08-31 14:02:04

最有可能的情况是 fopen 失败 - 您没有检查它的返回值来查看是否确实获得了有效的指针。 (当您尝试在下一行中使用该 NULL 指针时,您会遇到段错误。)

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

梦萦几度 2024-08-31 14:02:04

也许unsigned long的大小在机器上不一样。

以下程序在您的机器上打印什么?

#include <stdio.h>

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

使用gcc -std=c99 file.c编译。如果打印的大小确实不同,则需要将 unsigned long 替换为 uint32_t,并在以下位置添加 #include程序的开头:

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

上面假设“正确工作”的程序有 4 字节 unsigned long。如果不是,您需要将程序中的 4 替换为正确计算机上 unsigned long 的大小。

如果这是差异的原因,那么您现在知道了读写二进制数据的问题之一:您必须非常小心大小、字节顺序等。

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.

蓝梦月影 2024-08-31 14:02:04

我刚刚在 godaddy 遇到了这个问题,发现 FTP 客户端以 ASCII 格式上传,而不是二进制格式。我在上传之前将扩展名更改为.bin,现在可以正常使用了。

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.

逆夏时光 2024-08-31 14:02:04

我最初的猜测是文件无法打开,因此 io 为 NULL。

但韦德是对的:您应该首先在程序中添加一些错误处理 - 至少这会让您(和我们)更好地了解出了什么问题。

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.

尝蛊 2024-08-31 14:02:04

我的猜测是,服务器上的 sizeof(long) 是 8(因为它是 64 位系统),而本地计算机上的 sizeof(long) 是 4(假设是 32 位计算机)。因此,计算出的文件偏移量将错误 2 倍。如果您需要转到文件中的特定偏移量,则应该使用固定大小类型 - 即 uint32_t 等。

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.

如果没有 2024-08-31 14:02:04

首先,您没有向我们提供有关错误发生位置的上下文。

其次,在人们花费时间之前,您需要添加错误检查。

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.

空城之時有危險 2024-08-31 14:02:04

也许“index.dat”不在您的服务器上,但在您的计算机上。因为你用“rb”打开它,并且在 fopen 之后没有检查 io,所以很可能做到这一点。

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.

谜泪 2024-08-31 14:02:04

可以在服务器上运行gdb吗?如果是这样,请在启用调试的情况下构建(gcc 的 -g 选项)并在 gdb 中运行它。这会告诉你程序哪里失败了。方法如下(将 <> 中的内容替换为相关信息):

# gdb <program>

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

gdb 将捕获段错误并显示崩溃的行。

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.

羞稚 2024-08-31 14:02:04

我认为您正在阅读超出文件限制的内容。我添加了一部分来检查文件大小并确保您在文件限制内阅读。

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

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;
}
滥情哥ㄟ 2024-08-31 14:02:04

将代码的中间部分更改为:

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");

并查看运行程序时打印哪些行。这应该会提示您问题到底出在哪里。

编辑:当我说函数调用“有效”时,我的意思是“没有导致段错误”。理想情况下,您需要检查对 fseekfread 的每次调用,以确保它们没有遇到任何错误,但您提到您已经到了最后期限,所以这只是一些错误fast-n-dirty 错误跟踪来尝试追踪段错误。

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.

你好,陌生人 2024-08-31 14:02:04

也许您应该尝试为找到的变量和定位变量分配一些内存?

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文