C 只有在调试模式下运行时,程序才会接收SIGSEGV(分段故障)信号

C 只有在调试模式下运行时,程序才会接收SIGSEGV(分段故障)信号,c,segmentation-fault,dynamic-memory-allocation,clion,C,Segmentation Fault,Dynamic Memory Allocation,Clion,我有一个非常简单的c程序: #define Carta struct cartaStruct* int main(){ Carta carta = (Carta) malloc(sizeof(Carta)); carta->seme[0] = '\0'; carta->valore = 3; carta->posizione = -1; carta->next = null; carta->previous = nu

我有一个非常简单的c程序:

#define Carta struct cartaStruct*

int main(){
    Carta carta = (Carta) malloc(sizeof(Carta));
    carta->seme[0] = '\0';
    carta->valore = 3;
    carta->posizione = -1;
    carta->next = null;
    carta->previous = null;

    printCard(carta);

    Carta carta2 = (Carta) malloc(sizeof(Carta));
    carta2->seme[0] = '\0';
    carta2->valore = 2;
    carta2->posizione = -1;
    carta2->next = null;
    carta2->previous = null;

    printCard(carta2);
}
其中,
cartaStruct
是表示纸牌卡的结构:

struct cartaStruct {
    int valore; //card value
    char seme[20]; //card suit
    int posizione; //card position in a line of cards
    struct cartaStruct *next;
    struct cartaStruct *previous;
};
printCard
功能只需打印出卡片值、套装和位置:

void printCard(Carta carta) {
    if (carta != null) {
        printf("\nseme: %s", carta->seme);
        printf("\nvalore: %i", carta->valore);
        printf("\nposizione: %i", carta->posizione);
        printf("\n");
    } else {
        printf("La carta è vuota");
    }
}
现在,当我正常运行main时(两张卡都打印了我分配给它们的数据,进程以退出代码0结束),一切都按照预期工作,但当我在调试模式下运行它时,当我声明
carta2
并通过调用
malloc
对其进行初始化时,我会得到一个SIGSEGV(分段故障)信号

我知道分段错误意味着进程试图访问一些不属于它的内存地址,但我在这里什么时候这样做?为什么只有在调试模式下运行程序时才会发生这种情况

如果有帮助的话,我正在将CLion ide与CMake一起使用。

此内存分配

Carta carta = (Carta) malloc(sizeof(Carta));
这是错误的。你需要写作

Carta carta = (Carta) malloc(sizeof(`struct cartaStruct`));
也就是说,您需要为结构类型的对象而不是结构类型的指针分配内存

或者你可以写

Carta carta = (Carta) malloc(sizeof( *carta ));

其他问题如下:

  • 不要在C中强制转换
    malloc
    ,它隐藏了一个严重的警告,
    sizeof
    运算符的参数似乎无效
  • Carta Carta=(Carta)malloc(sizeof(Carta));
    
    必须更改为:

    Carta-Carta=malloc(sizeof(struct-cartaStruct));
    
    或者,您可以使用这种互锁技术,即使用指针本身来接收动态内存,以用作
    sizeof

    Carta Carta=malloc(sizeof(*Carta));
    
  • 使用
    NULL
    (大写)代替
    NULL
    (小写)
    [注:仅报告第一次出现的错误,可能还有其他地方]
  • carta->next=null;
    carta->previous=null;
    
    应改为:

    carta->next=NULL;
    carta->previous=NULL;
    
    为什么只有在调试模式下运行程序时才会发生这种情况

    因为未定义的行为或多或少会因某种原因而表现出不同的表现形式。你确实有未定义的行为

    我什么时候[访问不属于我的内存]在这里

    Carta
    定义如下

    #define Carta struct cartaStruct*
    
    …分配,例如

        Carta carta = (Carta) malloc(sizeof(Carta));
    
    。。。这是不正确的。您正在分配足够的空间来存储类型为
    struct cartaStruct*
    (指针)的对象,而您需要的是足够大的空间来容纳类型为
    struct cartaStruct
    的结构。此后,当您试图通过指针
    carta
    访问分配的内存时,您超出了分配空间的界限

    您可以这样修复它:

        Carta carta = malloc(sizeof(struct cartaStruct));
    
    ,但通常的建议是使用接收指针的变量来确定所需的大小,如下所示:

        Carta carta = malloc(sizeof(*carta));
    
    这将为
    carta
    指向的任何类型的对象提供足够的空间,即使您稍后更改该对象


    作为旁注,使用宏作为类型名的速记是非常罕见的。使用C的内置机制指定类型别名,即
    typedef
    ,更好、更安全:

    typedef struct cartaStruct *Carta;
    
    Carta Carta=(Carta)malloc(sizeof(Carta))
    这不应该是
    Carta Carta=(Carta)malloc(sizeof(Carta))
    sizeof(carta)
    而不是
    sizeof(carta)
    No,@sourabhchour。那里的分配规模存在问题,但您建议的特定更改根本没有任何区别。