C语言malloc()的一个问题——堆越界的一个错误。

本文详细探讨了如何正确使用malloc分配内存及free释放内存的方法,通过实例演示了字符串复制过程中的堆溢出问题,并提供了避免此类错误的有效策略。

malloc函数分配得到的空间是存储在堆区的。

系统推出后是不会被释放的,必须由程序员自己用free释放。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <malloc.h> 
int main()
{
	int address;
char *q;
	char *p=(char *)malloc(sizeof(char)*10);
q=strcpy(p,"chenhuijie is a good boy");

	printf("p:%s(%p),q:%s(%p)\n",p,p,q,q);

	address=(int)p;

	printf("int:%p",address);

	printf("the string is %s\n",(char *)address);

	free(p);

	

	//p++;


}

在调试时,单步调试至free(p)时。发生如下错误。


原来是发生了堆越界了。

	char *p=(char *)malloc(sizeof(char)*10);
q=strcpy(p,"chenhuijie is a good boy");

分配的堆空间为10个byte。多出来的字符被放置在10之后的内存中。一不小心发生了越界。才出现了这个堆被破坏的错误。


为了提高健壮性,应改为如下:

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

#define m_len 30
int main()
{
	int address;
	
    char *q="chenhuijie is a good boy";
	char *p=(char *)malloc(sizeof(char)*m_len);


	assert((strlen(q)+1)<m_len);

    q=strcpy(p,q);

	printf("p:%s(%p),q:%s(%p)\n",p,p,q,q);

	address=(int)p;

	printf("int:%p",address);

	printf("the string is %s\n",(char *)address);

	free(p);

	

	//p++;


}

主要是增加了长度检查的功能。为什么
strlen(q)+1)
这样呢?是因为strlen()返回的是字符串不含结尾符的字符个数。
### C语言中逐个字符添加到字符串的方法 在C语言中,可以通过动态分配内存或者手动管理静态数组来实现逐个字符添加到字符串的功能。以下是两种常见的方法: #### 方法一:使用固定大小的字符数组 通过预先定义一个具有足够大容量的字符数组,并利用索引来跟踪当前已填充的位置,可以逐步向该数组追加字符。 ```c #include <stdio.h> #define MAX_SIZE 100 int main() { char str[MAX_SIZE] = ""; // 初始化为空字符串 int index = 0; // 当前位置索引 // 假设要添加的字符序列是 'a', 'b', 'c' char ch; for (ch = 'a'; ch <= 'c'; ch++) { if (index >= MAX_SIZE - 1) break; // 防止越界 str[index++] = ch; // 将字符放入当前位置并移动索引 } str[index] = '\0'; // 结束符标记字符串结束 printf("最终字符串:%s\n", str); return 0; } ``` 这种方法简单直观,但存在一个问题——如果预估不足,则可能导致缓冲区溢出[^1]。 #### 方法二:使用动态内存分配 为了克服上述问题,还可以采用`malloc()`和`realloc()`函数动态调整存储空间大小。这种方式更加灵活但也稍微复杂一些。 ```c #include <stdio.h> #include <stdlib.h> void appendString(char **strPtr, size_t *capacity, size_t *length, char c) { if (*length == *capacity) { // 如果长度达到上限则扩展两倍容量 *capacity *= 2; *strPtr = realloc(*strPtr, *capacity); // 扩展内存 if (!*strPtr) exit(EXIT_FAILURE); // 内存分配失败退出程序 } (*strPtr)[(*length)++] = c; // 追加新字符至末尾 } int main() { size_t capacity = 8; // 初始容量设置为8字节 size_t length = 0; // 实际使用的长度初始值为零 char *dynamicStr = malloc(capacity); // 动态申请一块区域作为起始容器 dynamicStr[0] = '\0'; char ch; for (ch = 'A'; ch <= 'Z'; ch += 5) { // 示例循环添加部分字母表项 appendString(&dynamicStr, &capacity, &length, ch); } dynamicStr[length] = '\0'; // 补充终止标志位'\0' puts(dynamicStr); free(dynamicStr); // 记得释放资源以免泄漏 return 0; } ``` 此代码片段展示了如何创建一个新的辅助功能appendString(), 它负责检查现有空间是否充足以及必要时增加额外的空间以便容纳新增加的数据单元[^2]。 以上就是关于在C语言里怎样一步步构建字符串的一些基本技巧介绍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值