【问题标题】:C - segmentation fault on long running while loopC - 长时间运行的while循环出现分段错误
【发布时间】:2014-08-27 07:44:44
【问题描述】:

我使用内置运动传感器(由硬盘主动保护系统使用)或通过按钮手动在 Thinkpad X41 可转换笔记本电脑上编写了用于旋转屏幕的小守护程序。程序运行良好,但经过一段时间(5 到 15 分钟)后会因段错误而崩溃。

我知道互联网上有很多用 bash 或 python 编写的脚本来执行此操作,但它们都不适合我的需求和对程序应该如何工作的愿景。 我知道例如提到的 bash 可能对此更好,但与 C 相比,我对它的经验为零,在 C 中,我从几节高中课程中获得了最少的基本经验,所以我选择了这个。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define TRUE 1
#define FALSE 0
#define NIL -1

#define XRANDR_GREP_COMMAND "xrandr -q --verbose|grep LVDS1|cut -b37-37"
#define DAEMON_LOCK_FILE "/dev/shm/thinkrotate.lock"
#define DAEMON_STATE_FILE "/dev/shm/thinkrotate.st"
#define SWIVEL_STATE_FILE "/sys/devices/platform/thinkpad_acpi/hotkey_tablet_mode"
#define GYRO_STATE_FILE "/sys/devices/platform/hdaps/position"

#define BUBBLE_TERMINATED "notify-send 'Ukončenie programu' 'ThinkRotate démon dostal príkaz na ukončenie'"
#define BUBBLE_SWIVEL_DOWN "notify-send 'Notebook v tablet móde' 'Veko bolo sklopené, aktivovaná automatická rotácia'"
#define BUBBLE_SWIVEL_UP "notify-send 'Notebook v štandartnom režime' 'Rotácia je deaktivovaná'"
#define BUBBLE_RETURN_POSITION "notify-send 'Automatická rotácia zapnutá' 'Pre vypnutie automatickej rotácie obrazu stlačte tlačítko rotácie.'"
#define BUBBLE_START_MANUAL_ROTATION "notify-send 'Automatická rotácia vypnutá' 'Rotácia bude zapnutá znovu až pri návrate do tejto polohy, dovtedy na otáčanie obrazu používajte tlačidlo.'"

#define SWIVEL_DOWN_COMMANDS ""
#define SWIVEL_UP_COMMANDS ""
#define WIDTH_COMMANDS ""
#define HEIGHT_COMMANDS ""

int get_lock(void) {
    int fdlock;
    struct flock fl;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_len = 1;
    if((fdlock = open(DAEMON_LOCK_FILE, O_WRONLY|O_CREAT, 0666)) == -1) { return 0; }
    if(fcntl(fdlock, F_SETLK, &fl) == -1) { return 0; }
    return 1;
}

int next_rotation(int direction) {
    int next;
    int pos;
    pos = current_pos();
    if (direction == 1) {
        switch (pos) {
            case 0:
                next = 1;
            break;
            case 1:
                next = 2;
            break;
            case 2:
                next = 3;
            break;
            case 3:
                next = 0;
            break;
        }
    } else if (direction == 2) {
        switch (pos) {
            case 0:
                next = 3;
            break;
            case 1:
                next = 0;
            break;
            case 2:
                next = 1;
            break;
            case 3:
                next = 2;
            break;
        }
    }
    return next;
}

int current_pos(void) {
    FILE *frotpos;
    char rotpos;
    int pos;
    frotpos = popen(XRANDR_GREP_COMMAND, "r");
    fscanf(frotpos, "%c", &rotpos);
    fclose(frotpos);
    switch (rotpos) {
        case 110:
            pos = 0;
        break;
        case 108:
            pos = 1;
        break;
        case 105:
            pos = 2;
        break;
        case 114:
            pos = 3;
        break;
    }   
    return pos;
}

void rotate(int poz) {
    char buff[32];
    if ((poz == 2)||(poz == 0)) {
        system(WIDTH_COMMANDS);
    } else {
        system(HEIGHT_COMMANDS);
    }
    sprintf(buff, "xrandr -o %i", poz);
    system(buff);
}

int main(int argc, char *argv[]) {

    if(!get_lock()) {
        if (argc >= 2) {
            int cmd; 
            FILE *fparams;
            fparams = fopen(DAEMON_STATE_FILE, "w");
            if (!strncmp(argv[1], "r", 1)) { cmd = 1; }
            else if (!strncmp(argv[1], "l", 1)) { cmd = 2; }
            else if (!strncmp(argv[1], "k", 1)) { cmd = 0; }
            fprintf(fparams, "%i", cmd);
            fclose(fparams);
        }
        return 1;
    }

    int autorotate = TRUE;
    int prevmode = NIL;
    FILE *fstate;
    int tabletmode;
    FILE *fgyrovals;
    char gyroval_x[5];
    char gyroval_y[5];
    int x;
    int y;
    FILE *fargs;
    int argum = NIL;
    int next_p;
    int prev_p = current_pos();
    int last_auto_p = NIL;

    while (TRUE) {
        fstate = fopen(SWIVEL_STATE_FILE, "r");
        fscanf(fstate, "%d", &tabletmode);
        if (fargs = fopen(DAEMON_STATE_FILE, "r")) {
            if (fscanf(fargs, "%d", &argum) == NIL) { argum = NIL; }
        }
        fargs = fopen(DAEMON_STATE_FILE, "w");
        fclose(fargs);
        fclose(fstate);

        if (argum == 0) { 
            system(BUBBLE_TERMINATED);
            return 1; 
        }

        if (prevmode != tabletmode) {
            if (tabletmode) {
                system(BUBBLE_SWIVEL_DOWN);
                system(SWIVEL_DOWN_COMMANDS);
            } else {
                system(BUBBLE_SWIVEL_UP);
                system(SWIVEL_UP_COMMANDS);
                rotate(0);
            }
        }

        if (tabletmode) {
            if (argum == 1 || argum == 2) {
                next_p = next_rotation(argum);
                if (next_p == last_auto_p) {
                    rotate(next_p);
                    autorotate = TRUE;
                    last_auto_p = NIL;
                    system(BUBBLE_RETURN_POSITION);
                } else if ((autorotate)&&(current_pos() == last_auto_p)) {
                    autorotate = FALSE;
                    system(BUBBLE_START_MANUAL_ROTATION);
                } else {    
                    if (autorotate) {
                        system(BUBBLE_START_MANUAL_ROTATION);
                        last_auto_p = current_pos();
                    } else {
                        rotate(next_p);
                    }
                    autorotate = FALSE;
                }
            }
            if (autorotate) {
                fgyrovals = fopen(GYRO_STATE_FILE, "r");
                fscanf(fgyrovals, "(%4[^,], %4[^)]", &gyroval_x, &gyroval_y);
                fclose(fgyrovals);
                x = atoi(gyroval_x);
                y = atoi(gyroval_y) * (-1);
                if (y < 465) {
                    if (x < 210) {
                        next_p = 1;
                    } else if (x > 425) {
                        next_p = 3;
                    } else {
                        next_p = 2;
                    }
                } else if (y > 525) {
                    if (x < 210) {
                        next_p = 1;
                    } else if (x > 425) {
                        next_p = 3;
                    } else {
                        next_p = 0;
                    }
                } else {
                    if (x < 305) {
                        next_p = 1;     
                    } else if (x > 345) {
                        next_p = 3;
                    }
                }
                if (next_p != prev_p) {
                    rotate(next_p);
                    prev_p = next_p;
                }   
            } 
        } else {
            if (argum == 1 || argum == 2) {
                system(BUBBLE_SWIVEL_UP);
            }
        }           
        prevmode = tabletmode;
        sleep(1);
    }
    return 0;
}

【问题讨论】:

  • TL;博士!请将代码缩小到显示您的问题的最小可能代码,Minimal, Complete, and Verifiable example
  • if (fargs = fopen(DAEMON_STATE_FILE, "r")) { if (fscanf(fargs, "%d", &argum) == NIL) { argum = NIL; } } fargs = fopen(DAEMON_STATE_FILE, "w");这看起来不对,您正在打开文件以进行写入,而它已经打开以供读取。
  • 请永远不要说“程序运行良好”。
  • 另外,总是检查fopen的结果。
  • 您是否尝试过使用调试器查看程序崩溃的位置?

标签: c while-loop rotation segmentation-fault


【解决方案1】:

感谢用户“启发”的评论。现在程序运行了一个多小时,没有段错误。

if (fargs = fopen(DAEMON_STATE_FILE, "r")) {
    if (fscanf(fargs, "%d", &argum) == NIL) { argum = NIL; }
    fclose(fargs);
}
fargs = fopen(DAEMON_STATE_FILE, "w");
fclose(fargs);

如前所述,下次打开文件之前应该关闭文件。

【讨论】:

    猜你喜欢
    • 2018-09-27
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    相关资源
    最近更新 更多