我正在制作一个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);
}
}
答案 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)
除了之前的答案之外的一些注释:
大多数现代类Unix系统在标准库中都有asprintf()和vasprintf(),它们自己分配缓冲区。使用它们比计算所需的大小,分配和调用sprintf()更简单,即使它们过分分配了一些。
填充缓冲区然后使用write()将其打印到stdout看起来就像简单的printf()一样无法复杂化。使用stdio执行此类任务要好得多,除非您使用stdio无法稳定处理的内容(作为非阻塞I / O)。
你正在执行的任务更适合某些脚本语言(Perl,Python,Tcl,Ruby,等等),除非一些外部奇怪的情况迫使你使用C; C应该以Unix的方式来实现更接近内核和低级别的区域。参见例如"The Art of Unix Programming"用于推理。