vs推荐的scanf_s和内存泄露问题

Ark_Xu 2010-07-12 12:51:40
不理解为什么 scanf 在读取时不检查边界,就可能造成内存泄露
以前知道的只有申请的指针变量不被回收的时候会产生内存泄露

还有重新启动后泄露的内存会怎样 不是真正的永远不可用了吧?


char ch[10];
scanf_s("%s", ch);
printf("%s", ch);

用 vs08 如果 scanf_s 函数不加最后一个参数警告和错误都没有
那它这里起到什么作用呢 不是和 scanf 一样了吗?

另外 这里如果我写成

char ch[10];
scanf_s("%s", ch, 10);
printf("%s", ch);

这时接受参数:1234567890
结果观察了下 ch 是空的 不应该是 123456789 吗?
什么也没打印出来 怎么回事
...全文
614 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
fanster28_ 2010-07-15
  • 打赏
  • 举报
回复
理解清楚字符串的定义没,如果没有还是回去看看书吧

关于%多少c这用用法的含义也自己查吧
Ark_Xu 2010-07-15
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 fanster28_ 的回复:]

理解清楚字符串的定义没,如果没有还是回去看看书吧

关于%多少c这用用法的含义也自己查吧
[/Quote]
C 里字符串是字符数组
% 多少 c 是读几个字符到缓存
感觉我理解了,但如上面说的感觉很乱
Ark_Xu 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 fanster28_ 的回复:]

不是的。
因为字符数组就是每个存一个字符
不用在结尾加'\0'结尾标志
所以就不能用printf输出,它不知道哪里结束,可以试一下,后面会显示出一段认不到的
[/Quote]
scanf_s("%10c", ch, 10);
这里说读 10 个 char 结果确实读入了 无视最后一个参数只能读 9 个
如果改成
scanf_s("%11c", ch, 10);
既是数组大小够了也没读进去,受到最后一个参数影响了
scanf_s("%s", ch, 10);
这里也是会受最后一个参数影响 读不进去

所以就感觉有些矛盾 理解不了 是不是只有字符数小于等于后面那个参数才有可能读啊
然后如果等于的话又得自己标记结束?
fanster28_ 2010-07-14
  • 打赏
  • 举报
回复
不是的。
因为字符数组就是每个存一个字符
不用在结尾加'\0'结尾标志
所以就不能用printf输出,它不知道哪里结束,可以试一下,后面会显示出一段认不到的
Ark_Xu 2010-07-14
  • 打赏
  • 举报
回复
写疵了...
回 #9 大牛
C 的字符串就是字符数组吧 为什么当字符数组使用就可以呢?
    char ch[10];
scanf_s("%10c",ch,10);

Ark_Xu 2010-07-14
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 fanster28_ 的回复:]
2 正因为其设计的目的,所以不会让你输入一段超过缓冲区的内容(溢出攻击)
所以当你的字符串长度超过指定长度时输入为空


char ch[10];
scanf_s("%s", ch, 10);



因为字符串结尾有'\0'
如果你当字符数组使用 为什么当字符数组使用就可以呢?

    char ch[10];
scanf_s("%10c",ch,10);

[/Quote]

C 的字符串就是字符数组吧
Ark_Xu 2010-07-12
  • 打赏
  • 举报
回复
还是不明白啊 除了重启后内存泄露问题
mochhk 2010-07-12
  • 打赏
  • 举报
回复
顶下学习了~~
fanster28_ 2010-07-12
  • 打赏
  • 举报
回复
1 不加参数无警告和错误原因是因为
int __cdecl scanf_s (
const char *format,
...
)

原型是可变参数函数,他不知道你有没有加
它是根据栈中的值推到的下面的每个参数的值(函数调用的时候参数压栈)

2 正因为其设计的目的,所以不会让你输入一段超过缓冲区的内容(溢出攻击)
所以当你的字符串长度超过指定长度时输入为空
char ch[10];
scanf_s("%s", ch, 10);

因为字符串结尾有'\0'
如果你当字符数组使用
	char ch[10];
scanf_s("%10c",ch,10);

最后ch里面就是你输入的10个字符

[Quote=引用 7 楼 ark_xu 的回复:]

多谢楼上,去查了下相关资料 了解了一点
但是下面两个问题还是不知道...

用 vs08 如果 scanf_s 函数不加最后一个参数警告和错误都没有
那它这里起到什么作用呢 不是和 scanf 一样了吗?

另外 这里如果我写成

char ch[10];
scanf_s("%s", ch, 10);
printf("%s", ch);

这时接受参数:123456789……
[/Quote]
ForestDB 2010-07-12
  • 打赏
  • 举报
回复
友情帮顶。
Ark_Xu 2010-07-12
  • 打赏
  • 举报
回复
多谢楼上,去查了下相关资料 了解了一点
但是下面两个问题还是不知道...

用 vs08 如果 scanf_s 函数不加最后一个参数警告和错误都没有
那它这里起到什么作用呢 不是和 scanf 一样了吗?

另外 这里如果我写成

char ch[10];
scanf_s("%s", ch, 10);
printf("%s", ch);

这时接受参数:1234567890
结果观察了下 ch 是空的 不应该是 123456789 吗?
什么也没打印出来 怎么回事
fanster28_ 2010-07-12
  • 打赏
  • 举报
回复
其实scanf_s 等的出现是因为scanf等容易被溢出攻击
djjlove_2008 2010-07-12
  • 打赏
  • 举报
回复
因为vs系列的是c++编译器,cin比scanf之类的更安全,如果你纯c编程用scanf在这个环境下,自然要有警告,办法是用cin,或者换c的编译器。

回答者: 何处淬吴钩 - 八级 2008-10-30 19:07

void scan改成这个
void scan(char **a)
{
scanf("%s",*a);
}
调用时用scan(&a);应该就可以了吧,这里的指针是局部值,用指针的指针来传递指针的值试试

回答者: fuchuangbob - 六级 2008-10-30 19:23

我把scanf_s改为scanf后,在VC6.0和TURBO 2.0上运行都没有问题啊.
输入string
输出
s1
t1
r1
i1
n1
g1
你为什么要用scanf_s呢,我刚才在网上查了一下,这是一个什么函数啊.我以前也没有见过,也没听说过啊!


因为scanf_s更加科学,通过指定后面的n,有效地防止了内在泄漏。
djjlove_2008 2010-07-12
  • 打赏
  • 举报
回复
我打编译器是microsoft visual studio 2005,我的源程序如下,注意注释的地方,就是scan函数中的scanf_s函数,程序运行正常,但是当输入字符串大于或等于8个字符时,链表的输出就不正常了,7个以下是正常的,其他的不改变,单单把scanf_s改为scanf可以解决这个问题,但是系统又会给一个警告。。。。要怎么解决啊。。要正常又没警告的。
scanf_s
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 1000
typedef struct LNode
{ char data;
struct LNode *next;
}LinkList;

typedef struct
{
char elem[MAXSIZE];
int top;
}SqStack;

int main()
{ LinkList *CreateList(LinkList *L,char a[],int n);
void scan(char a[]);
void display(LinkList *L);
char a[MAXSIZE];
LinkList *L;
L=(LinkList *)malloc(sizeof(LinkList));
L->next=NULL;
scan(a);
L=CreateList(L,a,strlen(a));
display(L);
return 1;
}
LinkList *CreateList(LinkList *L,char a[],int n)
{
LinkList *s,*r;
int i;
r=L;
for(i=0;i<n;i++)
{
s=(LinkList *)malloc(sizeof(LinkList));
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
return L;
}

void scan(char a[])
{
scanf_s("%s",a);//这一行
}
void display(LinkList *L)
{
LinkList *p=L->next;
while(p!=NULL)
{
printf("%c",p->data);
printf("1\n");//test
p=p->next;
}
printf("\n");
}

问题补充:关键是用scanf_s的话不正常。。。
昵称很不好取 2010-07-12
  • 打赏
  • 举报
回复
重启后都重新初始化了,内存不会继续泄露的
关于scanf_s请看msdn:
The scanf_s function reads data from the standard input stream stdin and writes the data into the location given by argument. Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format. If copying takes place between strings that overlap, the behavior is undefined.

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧