2012-03-25 45 views
0

我正在make一个makefile的创建者,但是我被困在sprintf上的这个错误中,最奇怪的是我有多个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); 
    } 
} 
+0

我最好的猜测是其中一个字符串不是空终止。当我第一次学习C时,我遇到了这个问题。 – forivall 2012-03-25 06:07:20

回答

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); 
+0

对不起,我发布的代码是旧的,TEMP分配是固定的,但分段错误不是来自TEMP,而是来自sprintf(f.name .....)。这就是我发现奇怪的,即使使用f.name = malloc(sizeof(char)*(strlen(direntp-> d_name)* 2 + 3 + 1))仍然会启动相同的错误。 – 2012-03-25 17:42:38

0

“%s /%SA”,所以我想如果“%s”为长度为n,则整个字符串将取n * 2 + 1 + 1 + 1 + 1 = 2n + 4而不是2n + 3 ...不要忘记终止'\ 0',,, ,但至于是否应该导致分段错误。 。我不知道......

//呀,很多关于字节这段代码分配的一些错误......

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即表明您字符串的结尾)

问候

+0

谢谢,但就像我在其他评论中说的那样,这不是错误,尽管TEMP现在有更正seg错误来自sprintf(f.name .....) – 2012-03-25 17:44:03

+0

sprintf(f.name,“% s /%sa“,direntp-> d_name,direntp-> d_name,我看到2 * strlen(direntp-> d_name)+ 3 char + 1额外字符(\ 0作为字符串结尾),您分配了2 * strlen(direntp - > d_name)+ 3 char只有你错过了你的字符串的\ 0空间,编辑arf没有看到你曾尝试过这种方式 – grifos 2012-03-25 21:38:47

0

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

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

  2. 填充缓冲区,然后使用write()将其打印到标准输出看起来像简单的printf()上的非现实复杂化。除非你使用stdio无法稳定处理的东西(作为非阻塞I/O),否则使用stdio执行此类任务会更好。

  3. 您正在执行的任务更适合某种脚本语言(Perl,Python,Tcl,Ruby,无论),除非某些外部奇怪的情况迫使您使用C; C被认为是以Unix的方式来完成更接近内核和低层次的领域。见例如"The Art of Unix Programming"的推理。

+0

这是我大学的一个项目,这就是为什么我必须使用C,我知道asprintf )更好,但我有一些限制,因为我可以使用哪些命令。 – 2012-03-25 17:34:37