繁体   English   中英

sprintf的分段错误

[英]Segmentation Fault with sprintf

我正在制作一个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);
    }
}

看起来您分配的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);

“%s /%sa”,所以我认为如果“%s”的长度为n,则整个字符串将为n * 2 + 1 + 1 + 1 + 1 + 1 = 2n + 4而不是2n + 3 ...不要忘记终止符'\\ 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-> d_name)+25,但我看到25个字符+ 3 * sizeof(direntp-> d_name)+1个额外的字符(您的\\ 0表示字符串的结尾)

问候

除了以前的答案,还有一些注意事项:

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

  2. 填充缓冲区,然后使用write()将其打印到stdout看起来像简单的printf()那样不必要的复杂。 除非您使用stdio无法稳定处理的内容(例如非阻塞I / O),否则将stdio用于此类任务会更好。

  3. 您执行的任务最好适合某些脚本语言(Perl,Python,Tcl,Ruby,等等),除非某些外部怪异的情况迫使您使用C;否则,您可能会遇到这种情况。 Unix中应该以C语言来实现更接近内核和底层的区域。 有关推理,请参见“ Unix编程的艺术”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM