复制内存出现问题

3
char *a=NULL;

char *s=NULL; 

a=(char *)calloc(1,(sizeof(char))); 

s=(char *)calloc(1,(sizeof(char))); 

a="DATA"; 

memcpy(s,a,(strlen(a))); 

printf("%s",s);

请问为什么它会打印出DATA½½½½½½½½■ε■?如何只打印出DATA?谢谢。

6个回答

6

C语言中的字符串以零字符值(nul)结尾。

strlen返回零之前的字符数。

所以你不会复制零。

printf会继续运行,打印s后面的内存中的任何内容,直到遇到零。

你只创建了一个大小为1的缓冲区,所以你在写入数据时会覆盖s后面的任何内容,并且在将a设置为文字之前泄漏了calloc给a分配的内存。

在找到字符串的长度后为s分配内存,再分配一个字节来包括nul终止符,然后将a复制到s中。你不需要为a分配任何内存,因为C运行时负责存储文字“DATA”。


2
你首先分配了内存,然后通过使用字符串文字重新赋值指针来丢弃该内存。你对的参数也看起来非常错误。
此外,不是一个字符串复制函数,它不包括终止符。你应该使用。
打印仅DATA的最佳方法似乎是:
puts("DATA");

你需要更清楚地表达你想做什么,才能得到关于指针/分配/复制的帮助。


2

Your

a="DATA";

将指向分配内存的指针清除。它不会将“DATA”复制到内存中。然而,这样做是不够的,因为


(注意:原文中有一句未完成的话,翻译时需要注意保留原文格式)
a=(char *)calloc(1,(sizeof(char))); 

分配一块单独的字符内存。但是

memcpy(s,a,(strlen(a)));

memcpy函数将指向字符串常量“DATA”的地址所指向的内容复制到指向s的内存中。但需要注意的是,s指向的是一段已分配的单个字符,如果复制超过一个字符,可能会覆盖其他位置的数据导致错误。

strlen(a)返回4(即“DATA”的长度),memcpy将刚好复制4个字符。但为了知道字符串在哪里结束,C语言约定在字符串末尾加上一个空字符('\0')。因此,“DATA”在内存中实际上是由'D''A''T''A''\0'组成的。

所有与字符串有关的函数都期望以空字符结尾,并在遇到空字符前一直输出字符串内容。

要复制字符串,请使用strcpy(或strncpy)函数,它会连同空字符一起复制。但需要注意的是,strcpy存在“安全”漏洞,因为可以溢出目标缓冲区。

然而,我看到的最大问题是你只为和s各预留了一个字符的内存空间,这样“DATA\0”是无处放置的。


2

strlen函数只计算字符串中的字符数量,不包括终止符'\0'。 没有这个终止符,printf函数就无法知道字符串的结尾。

解决方法: memcpy(s,a,(strlen(a)+1));


1

你需要在 DATA 字符串后面存储一个终止符 \0,这样 printf() 才会知道何时停止打印。

你可以用 strcat 替换 memcpy

strcat(s, a);

应该这样做。

然而,请注意,之前有一个错误:

calloc(1,sizeof(char)) 

只会分配一个字节!这显然不够!根据实现,您的程序可能会崩溃或不会崩溃。


1

您为1个字符保留了空间,因此当您在写入“DATA”时(它包括4个字符和一个用于标记字符串结尾的结尾符 \0 ),实际上使用了其他某个变量的内存。

a=(char *)calloc(1,(sizeof(char)));

对于这个例子,您需要5个或更多字符:

a=(char *)calloc(5, (sizeof(char)));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接