sementation fault

段错误主要指访问的内存地址超出了系统给这个进程的内存空间。

通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了。

1)错误的访问类型引起

1

2

3

4

5

6

7

8

9

10

11

12

13

#include <stdio.h>

 

#include <stdlib.h>

 

int main()

 

{

 

    char *c = "hello world";

 

    c[1] = 'H';

 

}

  上述程序编译没有问题,但是运行时弹出SIGSEGV。此例中,”hello world”作为一个常量字符串,在编译后会被放在.rodata节(GCC),最后链接生成目标程序时.rodata节会被合并到text segment与代码段放在一起,故其所处内存区域是只读的。这就是错误的访问类型引起的SIGSEGV。

(2)访问了不属于进程地址空间的内存

1

2

3

4

5

6

7

8

9

10

11

12

13

#include <stdio.h>

 

#include <stdlib.h>

 

int main()

 

{

 

    int* p = (int*)0xC0000fff;

 

    *p = 10;

 

} 

还有另一种可能,往受到系统保护的内存地址写数据,最常见就是给一个指针以0地址

1

2

3

4

5

6

7

int  i=0;

 

scanf ("%d", i);  /* should have used &i */

 

printf ("%d\n", i);

 

return 0; 

(3)访问了不存在的内存

 最常见的情况不外乎解引用空指针了,如:

int *p = null;

*p = 1;

在实际情况中,此例中的空指针可能指向用户态地址空间,但其所指向的页面实际不存在。

(4)内存越界,数组越界,变量类型不一致等

1

2

3

4

5

6

7

8

9

10

11

12

13

#include <stdio.h>

 

int  main()

 

{

 

        char test[1];

 

        printf("%c", test[10]);

 

        return 0;

 

} 

这就是明显的数组越界了,或者这个地址根本不存在。

(5)试图把一个整数按照字符串的方式输出

1

2

3

4

5

6

7

8

9

10

11

int  main()

 

{

 

        int b = 10;

 

        printf("%s\n", b);

 

        return 0;

 

} 

这是什么问题呢?由于还不熟悉调试动态链接库,所以我只是找到了printf的源代码的这里。

1

2

3

4

5

6

7

8

9

10

11

12

13

声明部分:

    int pos =0 ,cnt_printed_chars =0 ,i ;

  unsigned char *chptr ;

  va_list ap ;

%s格式控制部分:

case 's':

      chptr =va_arg (ap ,unsigned char *);

      i =0 ;

      while (chptr [i ])

      {...

          cnt_printed_chars ++;

          putchar (chptr [i ++]);

  }

    ​    ​仔细看看,发现了这样一个问题,在打印字符串的时候,实际上是打印某个地址开始的所有字符,但是当你想把整数当字符串打印的时候,这个整数被当成了一个地址,然后printf从这个地址开始去打印字符,直到某个位置上的值为\0。所以,如果这个整数代表的地址不存在或者不可访问,自然也是访问了不该访问的内存——segmentation fault。
    ​    ​类似的,还有诸如:sprintf等的格式控制问题,比如,试图把char型或者是int的按照%s输出或存放起来,如:

1

2

3

4

5

6

7

8

9

10

11

#include <stdio.h>

#include <string.h>

char c='c';

int i=10;

char buf[100];

printf("%s", c);        //试图把char型按照字符串格式输出,这里的字符会解释成整数,再解释成地址,所以原因同上面那个例子

printf("%s", i);            //试图把int型按照字符串输出

memset(buf, 0, 100);

sprintf(buf, "%s", c);    //试图把char型按照字符串格式转换

memset(buf, 0, 100);

sprintf(buf, "%s", i);   //试图把int型按照字符串转换

  

(6)栈溢出了,有时SIGSEGV,有时却啥都没发生

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CTC(Connectionist Temporal Classification)分割是一种被广泛应用于序列学习任务中的分割方法。它最初被应用于语音识别领域,用于解码语音信号对应的文字序列。CTC分割的思想是将输入序列与输出序列对齐,使得输入序列上的每一个时间步都能对应一个输出标记。 在CTC分割中,输入序列被表示为一个矩阵,例如语音识别中的声学特征矩阵。输出序列是一个包含所有可能标记的序列,包括目标标记和空白标记。空白标记用于建立标记间的空隙,以便更好地适应输入序列与输出序列的对齐。 CTC分割的目标是找到最可能对应于输入序列的输出序列。这通过计算条件概率来实现,即给定输入序列的条件下,得到输出序列的概率。CTC分割使用动态规划算法来计算这一条件概率,通过对输入序列上的所有可能对齐路径求和来得到最终的输出序列概率。 CTC分割具有很好的鲁棒性,它可以处理输入序列与输出序列之间的对齐问题,即输入序列和输出序列长度不一致的情况。同时,CTC分割还可以处理同一输出序列上的多个相同标记的情况,这对于一些序列学习任务非常重要,例如语音识别中的连续重叠发音。 总的来说,CTC分割是一种有效的序列分割方法,可以被应用于多个领域的序列学习任务中,如语音识别、手写识别等。通过对输入序列与输出序列的对齐和概率计算,CTC分割能够找到最可能对应的输出序列,为序列学习任务提供了一种可靠且灵活的解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值