与scanf类似的功能中存在内存泄漏问题

与scanf类似的功能中存在内存泄漏问题,c,memory,memory-management,memory-leaks,valgrind,C,Memory,Memory Management,Memory Leaks,Valgrind,在下面的代码中,我试图重新创建scanf以读取stdin中的所有内容,并在新行字符上断开,返回字符串中读取的所有字符 但问题是代码会泄漏一些内存,特别是在调用realloc时 我还想知道为什么使用get是一个危险的函数 test.c:警告:“get”函数很危险,不应使用。 我的代码:- #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_BUF_LEN 128 #def

在下面的代码中,我试图重新创建scanf以读取stdin中的所有内容,并在新行字符上断开,返回字符串中读取的所有字符

但问题是代码会泄漏一些内存,特别是在调用
realloc

我还想知道为什么使用
get
是一个危险的函数

test.c:警告:“get”函数很危险,不应使用。

我的代码:-

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

#define MAX_BUF_LEN 128
#define __cdecl

//0 - Success
//-1 - Error in input
//1 - Error
__cdecl int read_input(char *s,int len){

char c,*t;
int l,i=0;

if(s==NULL || len < 1)
    return -1;

while((c=getchar()) != '\n'){

    //check if sufficient memory
    //required + used > assigned 
    l=strlen(s);
    if(l + 2 > len){

        len += l + MAX_BUF_LEN;     //realloc max to avoid subsequent realloc as its costly!

        t = realloc(s,len);
        if(t!=NULL)
            s = t;
        else
            return 1;               //No space to store content
    }

    s[i++] = c;

}

s[i++] = '\0';      //Null terminate the Buffer
return 0;   
}

int main(int argc,char* argv[]){

int len = 5+1;
char *s = calloc(len,sizeof(char));

printf("Enter your name\n");

if(!read_input(s,len))
    printf("Hi %s\n",s);

free(s);

return 0;
}
编辑:-请参考下面随附的新代码

新代码:-

__cdecl int read_input(char **s,int len){

char c,*t;
int l,i=0;

if((*s)==NULL || len < 1)
    return -1;

while((c=getchar()) != '\n'){

    //check if sufficient memory
    //required + used > assigned 
    l=strlen((*s));
    if(l + 2 > len){

        len += l + MAX_BUF_LEN;     //realloc max to avoid subsequent realloc as its costly!

        t = realloc((*s),len);
        if(t!=NULL)
            (*s) = t;
        else
            return 1;               //No space to store content
    }

    *((*s)+i++) = c;

}

*((*s)+i) = '\0';       //Null terminate the Buffer
return 0;   
} 
它仍然存在一些问题。

以下是关于
问题的说明:

永远不要使用get()。由于无法在不事先知道数据的情况下判断GET()将读取多少个字符,并且由于GET()将继续存储超过缓冲区末尾的字符,因此使用GET()非常危险。它被用来破坏计算机安全。改用fgets()

发生泄漏问题的原因是指针
s
是按值传递的,因此任何更改(包括重新分配后的赋值)都是对其副本而不是原始指针进行的。因此,释放
s
只释放最初分配的内存,泄漏
realloc
-ed内存。要解决此问题,请更改
read\u input
以获取指向指针的指针,如下所示:

int read_input(char **ps,int len)

&s
传递到
读取输入
,并使用
(*ps)
代替函数体中的
s

您的操作不会将指针返回到分配的缓冲区。所以,
free(s)
并没有达到您的期望
realloc
不保证在同一位置提供额外空间。因此,缓冲区可以移动。一种解决方案是将指针传递给一个指针,或者返回指针而不是
int
,并使用NULL指示错误


PS-还有其他问题,这是非常不安全的代码。

在循环中,您使用:

l=strlen(s);
但是
s
在循环中的任何位置都没有以null结尾。因此,当您随后在上调用
strlen()
时,它将无法提供您所期望的内容,这可能是内存泄漏的原因。因此,请确保在循环中以null结束字符串


gets
是危险的,因为它允许您读取的空间超过分配的空间。

gets()是危险的,因为它不知道缓冲区实际有多大,因此无法防止在大输入行上缓冲区溢出。对于坏人来说,缓冲区溢出是一种非常常见的攻击向量。改用fgets()和stdin作为第一个参数,它允许您指定缓冲区的大小。

好吧,这可能不是问题,但似乎您正在用
\0
替换字符串的最后一个字符。不要将
i++
误用为
++i
i+1
s[i++]='\0'//Null终止缓冲区
应为
s[i]='\0'//Null终止缓冲区
,因为i本身会递增,所以数组以Null终止。我不再被使用,因此避免了额外的增量。
calloc
zero初始化内存块,因此
strlen
不会遇到问题,我想这是对的。我以为是malloc,事实并非如此。现在可以用了吗?
strlen
仍然存在一些问题,我将发布一个新的答案,其中包括
valgrind
结果以及我在代码中所做的更改。我理解你的意思。由于
realloc
的原因,内存位置可能会按照@Judge Maygarden的建议发生变化,这将给
free
造成问题。但是,如果我没有使用
Realloc
,我认为这段代码会完美地工作。我说得对吗?
int read_input(char **ps,int len)
l=strlen(s);