【问题标题】:Seg fault? Can you find it? cause I can't段错误?你能找到吗?因为我不能
【发布时间】:2010-10-31 09:46:53
【问题描述】:

到目前为止,我已经查看了大约 15 次,但无济于事。我不明白为什么这是段错误?它甚至没有到达没有意义的“打印”语句。错误代码确实有效(当我没有共享内存时)我有一个 load.c 程序,但它运行良好(我 100% 确定这一点)

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include "header.h"

//BEGIN MAIN FUNCTION
main()
{
    int id;             //ID to data shmem
    struct StudentInfo *infoptr;    //ptr to data
    int found = 0;          //found 'boolean'
    char input[15];         //user input buffer
    struct StudentInfo *beginptr;   //ptr to beginning of data
    int rcid;           //Read count ID to shmem
    int *rcptr;         //RC ptr
    int sema_set;           //ID to shared semaphores

    //Find the shmem at our ID
        id = shmget(KEY,SEGSIZE,0);
        if(id < 0)
        {
                perror("Query: shmget failed");
                exit(1);
        }

    //set the ptr to our shared mem and attach to program
        infoptr = (struct StudentInfo *)shmat(id,0,0);
        if(infoptr <= (struct StudentInfo *)(0))
        {
                perror("Query: shmat failed");
                exit(1);
        }

    //Get our RC in shared memory 
    rcid = shmget(RCKEY,READCOUNT,0);
    if(rcid < 0)
    {
        perror("Query: shmget failed");
        exit(1);
    }
    //Set ptr to shmem and attach to process
    rcptr = (int*)shmat(rcid,0,0);
    if(rcptr <= (int*)(0))
    {
        perror("Print: Shmat failed");
        exit(1);
    }

    //Get semaphores
    sema_set = semget(SEMA_KEY,NUM_SEMAPHS,0);
    if(sema_set < 0)
    {
        perror("Query: Semget failed");
        exit(1);
    }   

    //Set program to queue up to wait
    Wait(sema_set,1);

    //Increment the read counter
    *rcptr += 1;

    //If we are the first reader, stop writers
    if(*rcptr == 1)
    Wait(sema_set,0);

    //Signal readers
    Signal(sema_set,1);

    //Set our begin ptr
    beginptr = infoptr;

    //Begin user input loop
    while(1)
    {
    //Ask user for input IT DOESN"T EVEN GET TO HERE <--
    printf("Please input a student ID :");
    scanf("%s",input);

    //While the record is not found search  
    while(strcmp(infoptr->Name,"")!=0 && found != 1)
    {
        //If record found, print the record
        if((strncmp(input,infoptr->ID,9)) == 0)
        {
            //Set found
            found = 1;

            printf("\n%s\n",infoptr->Name);
                    printf("%s\n",infoptr->telNumber);
                    printf("%s\n",infoptr->Address);
                    printf("%s\n\n",infoptr->ID);
        }
        else
            infoptr++;
    }

    //If not found, print error message
    if(found == 0)
        printf("Record not found.\n");

    //Wait on readers
    Wait(sema_set,1);
    //Decrement
    *rcptr--;
    //If no readers left
    if(*rcptr == 0)
        Signal(sema_set,0); //Signal writers
    //Signal readers
    Signal(sema_set,1);
    exit(0);        
    }
}

标题

#define KEY  ((key_t)(11111)) /*change it to last five digits of your SSN*/
#define SEGSIZE  sizeof(struct StudentInfo)

#define NUM_SEMAPHS 2
#define SEMA_KEY   ((key_t)(1111)) /* change this to last four digits of SSN */

#define READCOUNT sizeof(int)   //Set the size of shmem for read count
#define RCKEY ((key_t)(4003))   //Set the key of the shmem for RCount

//Struct student info
struct StudentInfo{
  char Name[20];
  char ID[15];
  char Address[50];
  char telNumber[15];
};

//Checks the semaphore whether or not to wait
void Wait(int semaph, int n);
//Signals that it's ok to run
void Signal(int semaph, int n);
//Gets the semaphore information
int GetSemaphs(key_t k, int n);

【问题讨论】:

  • 1.你试过valgrind吗? 2.错误可能在Wait或Signal内部或header.h中的其他内容,我们不知道。
  • main() 必须声明返回一个 int
  • 在调试器中启动它,查看段错误发生的位置。这会给你一个提示。
  • 如果您希望我们在您的代码中找到错误,至少将其全部附上,这样我们就不会费力地编译它(即什么是 header.h?)
  • 抱歉,我附上了 header.h )。在 unix 中使用调试器的任何提示?这也不是我尝试过的主要 int() 东西,我的其他文件也没有。

标签: c segmentation-fault


【解决方案1】:

您的问题可能来自您对shmat 的使用。在 C 中,永远不要强制转换此类函数的返回类型。您觉得需要它可能意味着您收到了一条虚假的错误消息,原因是您缺少“sys/shm.h”标头。

在这种情况下发生的情况是 gcc 采用 int 的返回类型,通常是 32 位数量,并将其重新解释为指针。所以shmat给你的地址的上半部分丢失了。

作为一般规则,不要抛弃问题。如果所有标题都正确编写,C 中很少需要强制转换。转换系统函数的返回类型几乎总是错误的。

【讨论】:

  • 我们的教授给了我们示例代码,他是怎么得到的?我不会知道的更好。不过,它似乎与 G++ 配合得很好。但我的意思是我对共享内存很陌生,所以大部分类代码都是从他的示例代码 <_ infoptr="(struct" studentinfo>
  • 是的,在 C 语言中,不需要将 void* 指针转换为任何其他数据指针。 void* 是指针的全部类型,与其他指针(数据指针)的赋值兼容。正是从这种类型的演员阵容中出现了你的问题:对于 C 来说,一个未知的函数应该返回 int,然后你的演员阵容告诉他“我知道我在做什么”。所以在这里投射真的很糟糕,它隐藏了一个潜在的问题。你应该仔细指导你的教授采用更好的编程风格。
  • 是啊,我想我明白你现在在说什么了。我只是通过我的操作系统教授的示例代码/注释去。
【解决方案2】:

Valigrind 和 GDB 是你的朋友

请提供完整的代码,以便我们编译它并帮助您。盯着源代码并不是调试的神奇方法:)

确保您使用编译器上的调试选项(-g 等)进行编译。

否则,检查 valgrind 的 memcheck。编译好程序后,运行:

valgrind ./myprogram

你可能会得到类似于以下的输出:

==584== Use of uninitialised value of size 8
==584==    at 0x400480: segfaultme (p.c:6)
==584==    by 0x40049B: main (p.c:13)
==584== 
==584== Invalid write of size 4
==584==    at 0x400480: segfaultme (p.c:6)
==584==    by 0x40049B: main (p.c:13)
==584==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==584== 
==584== 
==584== Process terminating with default action of signal 11 (SIGSEGV)
==584==  Access not within mapped region at address 0x0
==584==    at 0x400480: segfaultme (p.c:6)
==584==    by 0x40049B: main (p.c:13)
==584==  If you believe this happened as a result of a stack
==584==  overflow in your program's main thread (unlikely but
==584==  possible), you can try to increase the size of the
==584==  main thread stack using the --main-stacksize= flag.
==584==  The main thread stack size used in this run was 10485760.

使用以下命令破解 GDB:

gdb ./myprog 然后输入 rreturn

您将获得有关段错误发生位置的更多信息:

(gdb) r
Starting program: /home/aiden/tmp/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400480 in segfaultme (p=0x0) at p.c:6
6       *p = 22;
Missing separate debuginfos, use: debuginfo-install glibc-2.11.2-1.x86_64
(gdb) bt
#0  0x0000000000400480 in segfaultme (p=0x0) at p.c:6
#1  0x000000000040049c in main () at p.c:13

输入 btreturn 也会给你一个回溯。在上面的例子中,我们可以看到 segfaultme()segfaultme() 的第 6 行我取消引用 p 是问题所在,它显示 segfaultme()main() 调用。

希望这会有所帮助!请记住尽可能多地接触对您有帮助的工具!

【讨论】:

  • 一般来说你是完全正确的,只是你的第一个也是最好的朋友是你的编译器。 OP 只是通过抛弃系统函数的返回值来欺骗他最好的朋友;-)
  • 谢谢这确实有帮助,在你们提到它之前我从来不知道 valgrind。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 2021-09-03
相关资源
最近更新 更多