You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何定位并解决C语言项目中的SIGSEGV(段错误)问题

排查并解决Cygwin下project1.exe的SIGSEGV错误(仅修改printandcombine.c/h)

在Cygwin环境编译运行project1.exe时触发SIGSEGV错误,调试器指向combine_like_terms函数,仅允许修改printandcombine.c和printandcombine.h文件,以下是项目相关代码及问题排查、解决方案:


原项目代码

printandcombine.h

#ifndef PRINTANDCOMBINE_H
#define PRINTANDCOMBINE_H

//Returns a string representation of the struct term_t
char * term_to_string(term_t * term);

//Prints a linkedlist in no specific order
void print_linklist(node_t * curr);

//Returns a new linkedlist that is the result of combining the like terms
node_t * combine_like_terms(const node_t * current_node_ptr);

#endif

printandcombine.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"

/* Functions */

char * term_to_string(term_t * term)
{
    char *str = malloc((sizeof(char)) * 1024);
    
    sprintf(str, "%d%c%d ", term->coefficient, term->var, term->exponent);
    printf("%s", str);

    free(str);

    return str;
}

void print_linklist(node_t * curr)
{
    printf("%s", term_to_string(curr->term));

    if (!(curr->next_node == NULL))
    {
        print_linklist(curr->next_node);
    }
}

node_t * combine_like_terms(const node_t * current_node_ptr)
{
    node_t *temp = (node_t *)current_node_ptr;

    node_t *out = malloc(sizeof(node_t));
    node_t *move = out;

    int x = 0;

    while (!(temp == NULL))
    {
        if (temp->term->exponent > x)
        {
            x = temp->term->exponent;
        }
        temp = temp->next_node;
    }
    
    for (; x >= 0; x--)
    {
        temp = (node_t *)current_node_ptr;
        int a = 0;
        while (!(temp == NULL))
        {
            if (temp->term->exponent == x)
            {
                a = a + temp->term->coefficient;
            }
        
        move->term->coefficient = a;
        move->term->var = 'x';
        move->term->exponent = x;
        if (x > 0)
        {
        move->next_node = (node_t *)malloc(sizeof(node_t));
        move = move->next_node;
        }
    }
            
}

return out;
}

其他关联代码(仅作参考,不可修改)

project1.c

/* This is your main file */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"common.h"
#include"buildlinklist.h"
#include"printandcombine.h"

int main() {
    node_t * node_ptr = NULL;
    node_t * new_node_ptr=NULL;

    printf("NAME: Name\n");
    
    /* Build linklist */
    read_objects(&node_ptr);

    
    /* Print the link list */
    printf("Original: ");
    print_linklist(node_ptr);
    
    /* Combine like terms in the link list and create a new link list */
    new_node_ptr=combine_like_terms(node_ptr);
    printf("\nCombined: : ");
    /* Print new combine linklist */
    print_linklist(new_node_ptr);

    printf("\nNAME: Name\n");
    free(node_ptr);
    free(new_node_ptr);
    return 0;


}

buildlinklist.h

#ifndef BUILDLINKLIST_H
#define BUILDLINKLIST_H

#include"common.h"


/* Read from a text file and put in to a term_t structure. Then create a linklist of node (each node has an element of term struct.)*/
void read_objects(node_t ** pointer_to_node_ptr);

/* Assign value to term_t object elements */
term_t * term_from_string(char * buff);

/* Add a node to the link list */
int add_node(node_t ** pointer_to_node_ptr, void * term);

#endif

buildlinklist.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"common.h"



/* Assign value to term_t object elements */
term_t * term_from_string(char * buff) {
    term_t * ret = malloc(sizeof(term_t));
    ret->coefficient=atoi(strtok(buff, " "));
    ret->var=*strtok(NULL, " ");
    ret->exponent=atoi(strtok(NULL, " "));
    return ret;
}


/* Add a node to the link list */
int add_node(node_t ** pointer_to_node_ptr, void * term) {
  int ret = 0;
  node_t * newnode_ptr = (node_t *) malloc(sizeof(node_t));
  if (newnode_ptr == NULL) {
    ret = -1;
  }
  else {
    newnode_ptr->term = term;
    newnode_ptr->next_node = *pointer_to_node_ptr;
    *pointer_to_node_ptr = newnode_ptr;
  }
  return ret;
}


/* Read from a text file and put in to a term_t structure. Then create a linklist of node (each node has an element of term struct.)*/
void read_objects(node_t ** pointer_to_node_ptr) {

    FILE *fp;
    char buffer[BUFFERLEN];
    fp = fopen("terms.txt", "r");

    while (fgets(buffer, BUFFERLEN,fp)) {
        term_t * this_term;
        this_term = term_from_string(buffer);
        add_node(pointer_to_node_ptr, this_term);
    }
    fclose(fp);
}

common.h

#ifndef COMMON_H
#define COMMON_H

#define BUFFERLEN 40

typedef struct{           /* struct to hold elements like: 3x4 */
    int coefficient;
    char var;
    int exponent;
} term_t;

typedef struct node {
  term_t * term;            /* pointer to term */
  struct node * next_node;  /* pointer to next node */
} node_t;

#endif

makefile

CC=gcc 
CFLAGS=-std=c11 -Wall -pedantic 

all: project1.c buildlinklist.o printandcombine.o
    $(CC) $(CFLAGS) project1.c buildlinklist.o printandcombine.o -o project1

buildlinklist.o: buildlinklist.c
    $(CC) $(CFLAGS) -c buildlinklist.c

printandcombine.o: printandcombine.c
    $(CC) $(CFLAGS) -c printandcombine.c
clean:
    rm -f *.o *~ project1.exe

错误排查分析

1. term_to_string函数的野指针问题

该函数中,先malloc分配字符串内存,打印后立即free,随后返回已释放的指针。print_linklist函数中使用这个野指针调用printf,会触发未定义行为,可能直接导致崩溃。

2. combine_like_terms函数的核心错误

  • 空指针解引用:创建node_t节点时,仅分配了节点本身的内存,但未为term指针分配term_t结构的内存,直接访问move->term->coefficient会触发SIGSEGV。
  • 死循环:内层while循环中未移动temp指针(缺少temp = temp->next_node;),导致循环永远无法退出,耗尽资源或触发错误。
  • 链表尾节点未置空:最后一个节点的next_node未设置为NULL,后续print_linklist遍历链表时会访问非法内存。
  • 不必要的const强制转换:将const node_t*强制转为node_t*,虽然语法合法,但违背了const语义,应改为const node_t* temp = current_node_ptr;避免修改原链表。

修正后的printandcombine.c代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"

char * term_to_string(term_t * term)
{
    // 分配足够内存,无需提前free
    char *str = malloc(1024 * sizeof(char));
    if (!str) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    sprintf(str, "%d%c%d ", term->coefficient, term->var, term->exponent);
    // 这里不再打印,由print_linklist负责,避免重复输出
    return str;
}

void print_linklist(node_t * curr)
{
    if (!curr) return; // 空链表直接返回,避免空指针访问
    
    char *term_str = term_to_string(curr->term);
    printf("%s", term_str);
    free(term_str); // 用完再释放内存

    if (curr->next_node != NULL)
    {
        print_linklist(curr->next_node);
    }
}

node_t * combine_like_terms(const node_t * current_node_ptr)
{
    if (!current_node_ptr) return NULL; // 处理空输入链表

    const node_t *temp = current_node_ptr;
    int max_exp = 0;

    // 找出最大指数
    while (temp != NULL)
    {
        if (temp->term->exponent > max_exp)
        {
            max_exp = temp->term->exponent;
        }
        temp = temp->next_node;
    }
    
    node_t *out = NULL;
    node_t **move = &out; // 使用二级指针简化链表构建

    for (int x = max_exp; x >= 0; x--)
    {
        temp = current_node_ptr;
        int total_coeff = 0;
        // 累加当前指数的所有系数
        while (temp != NULL)
        {
            if (temp->term->exponent == x)
            {
                total_coeff += temp->term->coefficient;
            }
            temp = temp->next_node; // 移动指针,避免死循环
        }

        // 系数为0的项可以跳过,减少无用节点
        if (total_coeff == 0) continue;

        // 分配节点和term内存
        *move = malloc(sizeof(node_t));
        if (!*move) {
            perror("malloc failed");
            exit(EXIT_FAILURE);
        }
        (*move)->term = malloc(sizeof(term_t));
        if (!(*move)->term) {
            perror("malloc failed");
            exit(EXIT_FAILURE);
        }

        // 设置term属性
        (*move)->term->coefficient = total_coeff;
        (*move)->term->var = 'x';
        (*move)->term->exponent = x;
        (*move)->next_node = NULL; // 每个节点默认next为NULL

        move = &((*move)->next_node); // 移动到下一个节点的指针
    }

    return out;
}

额外说明

  1. 修正后的term_to_string不再提前释放内存,而是由调用者print_linklist使用后释放,避免野指针。
  2. combine_like_terms改用二级指针构建链表,逻辑更清晰,同时跳过系数为0的项,优化链表结构。
  3. 新增了空指针检查,避免极端情况(如空输入链表)导致的崩溃。

内容的提问来源于stack exchange,提问作者dismembered

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:20:36