释放malloc';d内存出现故障

释放malloc';d内存出现故障,c,malloc,C,Malloc,我有一个相当简单的程序,我用snprintf写一个字符串,如果需要的话,我会扩展字符串的长度以适应我要写的内容。然后,我尝试添加到该字符串。它确实有效,但当我释放malloc'd变量时,它崩溃了 守则: #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int ac, char **av) { char buf[16]; char *str = buf;

我有一个相当简单的程序,我用snprintf写一个字符串,如果需要的话,我会扩展字符串的长度以适应我要写的内容。然后,我尝试添加到该字符串。它确实有效,但当我释放malloc'd变量时,它崩溃了

守则:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int ac, char **av) {
    char buf[16];
    char *str = buf;
    char *extra = NULL;
    int len;

    if(!av[1]) {
        return 0;
    }

    if((len = snprintf(str, 16, "%s", av[1])) >= 16) {
        printf("more than 15 chars, %d\n",len);
        if (extra = malloc((len + 1) * sizeof(char))) {
            snprintf(str = extra, len + 1, "%s", av[1]);
        }
    } else {
        printf("less than 15 chars, %d\n",len);
    }

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


    if((len = snprintf(str+strlen(str), 16, "%s", av[1])) >= 16) {
        printf("more than 15 chars, %d, required: %d\n",len,(len + strlen(av[1]) + 1));
        if ((extra = malloc((len + strlen(av[1]) + 1) * sizeof(char)) ) && strcpy(extra,str)) {
            str = extra;
            snprintf(extra+strlen(av[1]), len + 1, "%s", av[1]);
        }
    } else {
        printf("less than 15 chars, %d\n",len);
    }
    printf("%s\n", str);

    if(extra) {
        free(extra);
    }

    return 1;
}
现在我并不是你所说的C专家,所以这个错误可能相当简单,但我自己还没能解决这个问题/在网上找到任何有用的东西

谢谢你的帮助

编辑:

固定代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int ac, char **av) {
    char buf[16];
    char *str = buf;
    char *extra = NULL;
    int len;
    int ssize = 16;
    if(ac != 2)
    {
        return 0;
    }


    if((len = snprintf(str, 16, "%s", av[1])) >= 16) {
        printf("more than 15 chars, %d\n",len);
        if (extra = malloc((len + 1) * sizeof(char))) {
        ssize = (len + 1);
          snprintf(str = extra, len + 1, "%s", av[1]);
        } 
    } else {
        printf("less than 15 chars, %d\n",len);
    }

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

    char *extra2 = NULL;
    printf("space: %d (%d-%d)\n",ssize-strlen(str),ssize,strlen(str));
    if((len = snprintf(str+strlen(str), ssize-strlen(str), "%s", av[1])) >= ssize-strlen(str)) {
        printf("more than 15 chars, %d, required: %d (strlen: %d)\n",len,(len + strlen(av[1]) + 1),strlen(str));


        if ((extra2 = malloc((len + strlen(av[1]) + 1) * sizeof(char)) ) && strcpy(extra2,str)) {
          str = extra2;
        ssize = (len + strlen(av[1]) + 1);
          snprintf(extra2+strlen(av[1]), len + 1, "%s", av[1]);
        } else printf("failed extraing");
    } else {
        printf("less than 15 chars, %d\n",len);
    }
    printf("%s\n", str);

    if(extra) {
        free(extra);
    }
    if(extra2) {
        free(extra2);
    }

    return 1;
}
#包括
#包括
#包括
内部主(内部ac,字符**av){
char-buf[16];
char*str=buf;
char*extra=NULL;
内伦;
int-ssize=16;
如果(ac!=2)
{
返回0;
}
如果((len=snprintf(str,16,“%s”,av[1]))>=16){
printf(“超过15个字符,%d\n”,len);
if(extra=malloc((len+1)*sizeof(char))){
ssize=(len+1);
snprintf(str=extra,len+1,“%s”,av[1]);
} 
}否则{
printf(“少于15个字符,%d\n”,len);
}
printf(“%s\n”,str);
char*extra2=NULL;
printf(“空间:%d(%d-%d)\n”、ssize strlen(str)、ssize、strlen(str));
如果((len=snprintf(str+strlen(str),ssize-strlen(str),“%s”,av[1])>=ssize-strlen(str)){
printf(“超过15个字符,%d,需要:%d(strlen:%d)\n”,len,(len+strlen(av[1])+1),strlen(str));
if((extra2=malloc((len+strlen(av[1])+1)*sizeof(char))&&strcpy(extra2,str)){
str=extra2;
ssize=(len+strlen(av[1])+1);
snprintf(附加2+strlen(av[1]),len+1,“%s”,av[1]);
}else printf(“未完成的附加”);
}否则{
printf(“少于15个字符,%d\n”,len);
}
printf(“%s\n”,str);
如有(额外){
免费(额外);
}
若有(额外2){
免费(2);
}
返回1;
}

在字符串的第二个副本中,您使用此代码,它告诉snprintf()缓冲区中有16个字节:

if((len = snprintf(str+strlen(str), 16, "%s", av[1])) >= 16) {

但是您已将
str+strlen(str)
作为要写入的地址传递。显然,这个地址没有16个字节可用,只有1个字节(假设您最初输入的字符串长度超过16,然后分配了len+1字节)。因此,当您告诉snprintf()时,它有16次写入超过您分配的内存末尾,这有时只能在您尝试释放它时显示为问题。

您至少有2次问题

一,。您正在对照argv指针检查参数的数量。 如果只提供1个参数,这将导致核心转储,因为指针的argv数组在
av[1]

因此,与其跟随

 if(!av[1]) 
 {
    return 0;
}
您应该检查:

if(ac != 2)
{
   return 0;
}
二,。您的程序内存泄漏。您正在执行2
malloc
s,但正在用第二个malloced指针覆盖第一个malloced指针

三,。您的程序内存已损坏

if((len = snprintf(str+strlen(str), 16, "%s", av[1])) >= 16) {
str
的大小只有16。您最终将写入超过
str
大小的内容,从而导致损坏


因此,glibc抱怨释放问题主要是由于这种腐败。

谢谢!最后,我将缓冲区的大小存储在一个整数中,并在调用第一个malloc时更改它。然后我用那个整数替换16,减去strlen(str)。现在工作得很好!
if((len = snprintf(str+strlen(str), 16, "%s", av[1])) >= 16) {