使用sprintf进行分段错误

时间:2012-03-25 06:02:45

标签: c segmentation-fault printf

我正在制作一个makefile创建者,但是我在sprintf上遇到了这个错误,最奇怪的是我在错误之前有多个sprintf并且它们工作正常。

以下是代码:

if ( WIFEXITED(stat)  ){

    if ( WEXITSTATUS(stat) ) {

        if ( cFiles == 0 && cFolders == 0 ) {
            Crear(path);
        }

        cFolders = 1;
        TEMP = malloc( sizeof(char)*( strlen(direntp->d_name) + 25 ) );

        if ( TEMP == NULL ) {
            perror("Malloc Error: ");
            exit(1);
        }

        if ( sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name) < 0 ) {
        perror("Sprintf Error: ");
        exit(1);
        }

        write(STDOUT_FILENO,TEMP,strlen(TEMP));
        f.name = malloc( sizeof(char)*( strlen(direntp->d_name)*2 + 3 ) );

        if ( f.name = NULL ) {
            perror("Malloc Error: ");
            exit(1);
        } 
            //This is the one with the problem!!!       
            if ( sprintf(f.name, "%s/%s.a", direntp->d_name, direntp->d_name) < 0 ) {
            perror("Sprintf Error: ");
            exit(1);
        }

        l = AddToList(l,&f);
    }
}

4 个答案:

答案 0 :(得分:1)

似乎你没有将TEMP分配给足够大的

TEMP = malloc( sizeof(char)*( strlen(direntp->d_name) + 25 ) );

应该是:

TEMP = malloc( sizeof(char)*( strlen(direntp->d_name)*3 + 25 + 1 ) );

您正在打印d_name三次,并且还需要一个额外的字节用于空终止符。

同样,在这一行:

   f.name = malloc( sizeof(char)*( strlen(direntp->d_name)*2 + 3 ) );

应该是

   f.name = malloc( sizeof(char)*( strlen(direntp->d_name)*2 + 3 + 1) );

考虑空终止符。

使用这样的断言有助于确保计算正确:

    int TEMP_size = strlen(direntp->d_name)*3 + 25 + 1; 
    TEMP = malloc(sizeof(char)*TEMP_size);

    if ( TEMP == NULL ) {
        perror("Malloc Error: ");
        exit(1);
    }

    if ( sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name) < 0 ) {
      perror("Sprintf Error: ");
      exit(1);
    }
    assert(strlen(TEMP)+1==TEMP_size);

答案 1 :(得分:0)

“%s /%sa”,所以我认为如果“%s”的长度为n,则整个字符串将采用n * 2 + 1 + 1 + 1 + 1 = 2n + 4而不是2n + 3 ...不要忘记终止'\ 0',,, 但至于这是否会引起分段错误......我不知道......

//是的,关于在这段代码中分配的字节数有很多错误......

答案 2 :(得分:0)

您没有为此sprintf分配enougth内存:

sprintf(TEMP, "\n%s/%s.a: force\n\t$(MAKE) -C %s\n",direntp->d_name, direntp->d_name, direntp->d_name

你分配sizeof(direntp-&gt; d_name)+25但是我看到25个char + 3 * sizeof(direntp-&gt; d_name)+1个额外的char(你的\ 0表示你的字符串的结尾)

问候

答案 3 :(得分:0)

除了之前的答案之外的一些注释:

  1. 大多数现代类Unix系统在标准库中都有asprintf()和vasprintf(),它们自己分配缓冲区。使用它们比计算所需的大小,分配和调用sprintf()更简单,即使它们过分分配了一些。

  2. 填充缓冲区然后使用write()将其打印到stdout看起来就像简单的printf()一样无法复杂化。使用stdio执行此类任务要好得多,除非您使用stdio无法稳定处理的内容(作为非阻塞I / O)。

  3. 你正在执行的任务更适合某些脚本语言(Perl,Python,Tcl,Ruby,等等),除非一些外部奇怪的情况迫使你使用C; C应该以Unix的方式来实现更接近内核和低级别的区域。参见例如"The Art of Unix Programming"用于推理。