【问题标题】:Segmentation fault before main is executedmain 执行前的分段错误
【发布时间】:2016-04-15 15:31:56
【问题描述】:

由于某种原因,在我的任何代码在 main() 函数中实际执行之前,我遇到了分段错误。我尝试通过放入 printfs 来遵循执行线,但实际上没有执行任何操作。我在我的程序中看不到任何会导致堆栈溢出的内容,因为我什至几乎不使用内存。

如果有人比我有更好的眼睛并且能发现这个错误,那将非常感激!

主要:

#include "../inc/protos.h"


HistogramData *histogram_data;
bool signal_caught = false;
sem_t *semaphore_id;
int letter_count[kLetterCount] = { 0 };
int wait_time = 0;

int main(void)
{
    int shared_memory_id = 0;
    key_t shared_memory_key = 0;
    char buffer[kBufferLength] = { 0 };
    int heads = 0;
    int tails = 0;

    printf("1");

    histogram_data->signal_caught = false;

    signal(SIGINT, signal_handler);

    printf("2");

    //Get the key to the allocated shared memory
    shared_memory_key = ftok("/tmp", 'M');
    if(shared_memory_key == -1)
    {
        printf("(CONSUMER) Cannot allocate key.\n");
        return 1;
    }

    printf("3");

    //Look for shared memory every 10 seconds until it finds it
    while(true)
    {
        if((shared_memory_id = shmget(shared_memory_key, sizeof(histogram_data), 0)) == -1)
        {
            printf("4");
            printf("(CONSUMER) Shared Memory does not exist. Please run the Producer program.\n");

            sleep(kSleepTime);
        }
        else
        {
            printf("5");
            break;
        }
    }

    printf("(CONSUMER) Our Shared Memory ID is %d.\n", shared_memory_id);

    //Attach the structure to the shared memory
    histogram_data = (HistogramData*) shmat(shared_memory_id, NULL, 0);
    if(histogram_data == NULL)
    {
        printf("(CONSUMER) Cannot attach to Shared Memory.\n");
        return 3;
    }

    semaphore_id = sem_open("/HISTOGRAM_SEM", O_CREAT, S_IRUSR | S_IWUSR, 1);

    signal(SIGALRM, alarm_handler);

    //Set the watchdog timer to 2 seconds.
    alarm(kAlarmSeconds);

    //Detach from shared memory
    shmdt(histogram_data);

    return 0;
}



void signal_handler(int signal_number)
{
    printf ("(CONSUMER) Received a signal. SIGINT ID is %d\n", signal_number);

    histogram_data->signal_caught = true;

    // Send SIGINT to Producer2
    kill(histogram_data->producer2_pid, SIGINT);

    // Send SIGINT to Producer1
    kill(histogram_data->producer1_pid, SIGINT);
}


void print_line(int num)
{
    int hundreds = num / 100;
    num = num % 100;
    int tens = num / 10;
    num = num % 10;
    int ones = num;


    int i = 0;
    for(i = 0; i < hundreds; i++)
    {
        printf("*");
    }
    for(i = 0; i < tens; i++)
    {
        printf("+");
    }
    for(i = 0; i < ones; i++)
    {
        printf("-");
    }

    printf("\n");
}


void display_histogram(int letter_count[])
{
    int i = 0;

    printf("\n********** HISTOGRAM **********\n");
    for(i = 0; i < kLetterCount; i++)
    {
        printf("%c-%03d ", i + 65, letter_count[i]);
        print_line(letter_count[i]);
    }
}


void alarm_handler(int signal_number)
{
    int wait_time = 0;

    sem_wait(semaphore_id);

    int i = 0;
    for(i = 0; i < kDCReads; i++)
    {
        int* read_index = &histogram_data->read_index;

        if(histogram_data->circular_buffer[*read_index] != 0)
        {
            int read_data = histogram_data->circular_buffer[*read_index];
            histogram_data->circular_buffer[*read_index] = 0;
            ++letter_count[read_data - 65];

            if(*read_index == kCircleBufferSize)
            {
                *read_index = 0;
            }

            if(*read_index == histogram_data->write_index)
            {
                break;
            }
        }
    }

    if(signal_caught == true)
    {
        //Read and write indexes from the histogram data structure
        int* read_index = &histogram_data->read_index;
        int* write_index = &histogram_data->write_index;

        //Read data from buffer
        while(*read_index != *write_index)
        {
            if(histogram_data->circular_buffer[*read_index])
            {
                //Data read in from the circular buffer
                int read_data = histogram_data->circular_buffer[*read_index];

                //Mark element as read
                histogram_data->circular_buffer[*read_index] = 0;
                ++letter_count[read_data - 65];

                //Increment the elements
                (*read_index)++;
                if(*read_index == 256)
                {
                    *read_index = 0;
                }
                if(*read_index == *write_index)
                {
                    break;
                }
            }
        }

        //Display a histogram listing
        display_histogram(letter_count);
        return;
    }

    wait_time++;
    if(wait_time >= 5)
    {
        wait_time = 0;
        display_histogram(letter_count);
    }

    //Release semaphore lock
    sem_post(semaphore_id);

    //Set the alarm for the watchdog to be two seconds
    alarm(kAlarmSeconds);

    //Reactivate watchdog signal
    signal(signal_number, alarm_handler);   
}

protos.h:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <signal.h>
#include <semaphore.h>

#define kCircleBufferSize 256
#define kBufferLength 126
#define kLetterCount 20
#define kDCReads 60
#define kAlarmSeconds 2
#define kSleepTime 10

typedef struct HistogramData HistogramData;

struct HistogramData
{
    int read_index;
    int write_index;
    int is_wrap_around;
    pid_t producer1_pid;
    pid_t producer2_pid;

    char circular_buffer[kCircleBufferSize];

    bool signal_caught;
};


void signal_handler(int signal_number);
void print_line(int num);
void display_histogram(int letter_count[]);
void alarm_handler(int signal_number);

【问题讨论】:

  • 在每个调试提示中添加一个newline,例如printf("1\n");,以确保在发生段错误时不会丢弃输出缓冲区。
  • 如果一定要使用printf,在后面加上fflush(),保证缓冲区已经发送到输出端再继续。
  • @MichaelWalz - 我们可以将其作为所有已发布问题的要求吗?
  • 您也可以使用fprintf( stderr, ... ) 进行调试输出,因为stderr 没有缓冲,而将stdout 留作正常使用。

标签: c segmentation-fault stack-overflow


【解决方案1】:

由于某种原因,在我的任何代码在 main() 函数中实际执行之前,我遇到了分段错误。

您的一个预加载数据结构可能会导致堆栈溢出。你还有很多缓冲到输出,此外,你有几个地方使用printf(),但不要附加换行符\n来刷新控制台缓冲区。或者,您可以通过在您的 printf() 语句之后添加 fflush() 来关注 @sabbahillel 的评论。

【讨论】:

    【解决方案2】:

    您创建 histogram_data 作为指向 HistogramData 的指针,但不要创建 HistogramData 对象。然后,当您在 main 中调用 histogram_data-&gt;signal_caught = false 时,您的程序会取消引用 NULL 指针。
    相反,在使用指针之前为 HistogramData 分配内存(例如,histogram_data = malloc(sizeof *histogram_data);)。以后也不要忘记释放它。

    【讨论】:

    • OP 在通过调试器运行时会发现 :( --- 给男人一条鱼,yada yada yada
    • 不错,但 C 不是 C++。
    • 糟糕,我编辑错误并回滚了,抱歉。但是早点 +1。
    猜你喜欢
    • 1970-01-01
    • 2017-07-16
    • 2021-06-30
    • 2020-02-24
    • 2012-01-29
    • 2015-06-14
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多