服务器上的分段错误,但不是本地机器

时间:2010-03-12 21:49:32

标签: c segmentation-fault

如标题所述,该程序正在我的本地机器(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包含一个巨大的数组=&gt;位置。

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

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

11 个答案:

答案 0 :(得分:5)

最可能的事情是fopen失败了 - 你没有检查它的返回值,看你是否真的有一个有效的指针。 (当您尝试在下一行中使用该NULL指针时,会出现段错误。)

答案 1 :(得分:2)

可能机器上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 <inttypes.h>

#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的大小。

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

答案 2 :(得分:2)

我刚刚与godaddy遇到此问题,发现FTP客户端是以ASCII而不是Binary上传的。我在上传前将扩展程序更改为.bin,现在正常运行。

答案 3 :(得分:1)

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

但韦德是对的:你应该首先为你的程序添加一些错误处理 - 至少可以让你(和我们)更好地了解出错的地方。

答案 4 :(得分:1)

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

答案 5 :(得分:0)

首先,您没有告诉我们错误发生的位置。

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

答案 6 :(得分:0)

也许“index.dat”不在你的服务器上,而是在你的机器上。因为你用“rb”打开它而不是在fopen之后检查io就可以了。

答案 7 :(得分:0)

你可以在服务器上运行gdb吗?如果是,则在启用调试的情况下构建(gcc的-g选项)并在gdb中运行它。这将告诉你程序失败的地方。这是如何(用相关信息替换&lt;&gt;中的内容):

# gdb <program>

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

gdb将捕获segfault并显示崩溃的行。

答案 8 :(得分:0)

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

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

答案 9 :(得分:-1)

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

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的每次调用,以确保他们没有遇到任何错误,但您提到您处于截止日期,所以这只是一些快速错误的错误跟踪尝试追踪段错误。

答案 10 :(得分:-3)

也许你应该尝试为found和loc变量分配一些内存?