在下面的代码中,我试图重新创建scanf
以读取所有内容,stdin
并在换行符处中断,返回字符串中读取的所有字符。
但问题是代码会泄漏一些内存,尤其是在realloc
被调用时。
我也想知道为什么gets
使用危险功能
test.c: warning: the 'gets' function is dangerous and should not be used.
我的代码:-
#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;
}
瓦尔格林:
nimish:~/Desktop$ gcc -g -Wall test.c -o test
nimish~/Desktop$ clear && valgrind ./test --leak-check=full
==3670== Memcheck, a memory error detector
==3670== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==3670== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==3670== Command: ./test --leak-check=full
==3670==
Enter your name
Nimish Nicolus
==3670== Conditional jump or move depends on uninitialised value(s)
==3670== at 0x4027029: strlen (mc_replace_strmem.c:282)
==3670== by 0x804850E: read_input (test.c:23)
==3670== by 0x80485CD: main (test.c:51)
==3670==
==3670== Invalid read of size 1
==3670== at 0x40831BF: vfprintf (vfprintf.c:1623)
==3670== by 0x40891BF: printf (printf.c:35)
==3670== by 0x80485E6: main (test.c:52)
==3670== Address 0x41a5028 is 0 bytes inside a block of size 6 free'd
==3670== at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670== by 0x8048537: read_input (test.c:28)
==3670== by 0x80485CD: main (test.c:51)
==3670==
==3670== Invalid read of size 1
==3670== at 0x40A93A8: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1317)
==3670== by 0x408346F: vfprintf (vfprintf.c:1623)
==3670== by 0x40891BF: printf (printf.c:35)
==3670== by 0x80485E6: main (test.c:52)
==3670== Address 0x41a502c is 4 bytes inside a block of size 6 free'd
==3670== at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670== by 0x8048537: read_input (test.c:28)
==3670== by 0x80485CD: main (test.c:51)
==3670==
==3670== Invalid read of size 1
==3670== at 0x40A93BF: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1317)
==3670== by 0x408346F: vfprintf (vfprintf.c:1623)
==3670== by 0x40891BF: printf (printf.c:35)
==3670== by 0x80485E6: main (test.c:52)
==3670== Address 0x41a502b is 3 bytes inside a block of size 6 free'd
==3670== at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670== by 0x8048537: read_input (test.c:28)
==3670== by 0x80485CD: main (test.c:51)
==3670==
==3670== Invalid read of size 1
==3670== at 0x40A9330: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1349)
==3670== by 0x408346F: vfprintf (vfprintf.c:1623)
==3670== by 0x40891BF: printf (printf.c:35)
==3670== by 0x80485E6: main (test.c:52)
==3670== Address 0x41a5028 is 0 bytes inside a block of size 6 free'd
==3670== at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670== by 0x8048537: read_input (test.c:28)
==3670== by 0x80485CD: main (test.c:51)
==3670==
==3670== Invalid read of size 1
==3670== at 0x40A933C: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1348)
==3670== by 0x408346F: vfprintf (vfprintf.c:1623)
==3670== by 0x40891BF: printf (printf.c:35)
==3670== by 0x80485E6: main (test.c:52)
==3670== Address 0x41a502a is 2 bytes inside a block of size 6 free'd
==3670== at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670== by 0x8048537: read_input (test.c:28)
==3670== by 0x80485CD: main (test.c:51)
==3670==
Hi Nimis
==3670== Invalid free() / delete / delete[]
==3670== at 0x4025BF0: free (vg_replace_malloc.c:366)
==3670== by 0x80485F2: main (test.c:54)
==3670== Address 0x41a5028 is 0 bytes inside a block of size 6 free'd
==3670== at 0x402695A: realloc (vg_replace_malloc.c:525)
==3670== by 0x8048537: read_input (test.c:28)
==3670== by 0x80485CD: main (test.c:51)
==3670==
==3670==
==3670== HEAP SUMMARY:
==3670== in use at exit: 139 bytes in 1 blocks
==3670== total heap usage: 2 allocs, 2 frees, 145 bytes allocated
==3670==
==3670== LEAK SUMMARY:
==3670== definitely lost: 139 bytes in 1 blocks
==3670== indirectly lost: 0 bytes in 0 blocks
==3670== possibly lost: 0 bytes in 0 blocks
==3670== still reachable: 0 bytes in 0 blocks
==3670== suppressed: 0 bytes in 0 blocks
==3670== Rerun with --leak-check=full to see details of leaked memory
==3670==
==3670== For counts of detected and suppressed errors, rerun with: -v
==3670== Use --track-origins=yes to see where uninitialised values come from
==3670== ERROR SUMMARY: 23 errors from 7 contexts (suppressed: 11 from 6)
编辑:- 请参考下面附上的新代码
新代码:-
__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;
}
瓦尔格林:
==4767== Memcheck, a memory error detector
==4767== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==4767== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==4767== Command: ./test --leak-check=full
==4767==
Enter your name
Nimish Nicolus
==4767== Conditional jump or move depends on uninitialised value(s)
==4767== at 0x4027029: strlen (mc_replace_strmem.c:282)
==4767== by 0x8048516: read_input (test.c:23)
==4767== by 0x80485DE: main (test.c:51)
==4767==
Hi Nimish Nicolus
==4767==
==4767== HEAP SUMMARY:
==4767== in use at exit: 0 bytes in 0 blocks
==4767== total heap usage: 2 allocs, 2 frees, 145 bytes allocated
==4767==
==4767== All heap blocks were freed -- no leaks are possible
==4767==
==4767== For counts of detected and suppressed errors, rerun with: -v
==4767== Use --track-origins=yes to see where uninitialised values come from
==4767== ERROR SUMMARY: 6 errors from 1 contexts (suppressed: 11 from 6)
它仍然给出了一些问题。