声明:PTRQ开发问题解决专栏的文章是我在开发中遇到的一些问题,继承他人本着再小的问题也需要有人解答的想法,将这些问题和答案整理出来。
(本文解决方法可能不唯一,欢迎和我讨论问题,同时也欢迎标注转载)
一、前言
typedef struct Base_Context
{
unsigned int sz;//记录当前有效信息数量
unsigned int capacity;//记录当前最大容量
unsigned int id;
unsigned short line;//记录行数
unsigned short contextcount;
char context_paragraph[0];//每段内容
}Base_Context;
我在开发中构造的是变长数组+变长结构体,需要特别注意的是变长数组≠变长结构体。
变长数组
变长数组是分配在栈上的,而malloc函数分配而来的空间是堆上面的。使用变长数组,可能稍微不注意就会造成栈溢出,而调用malloc函数来分配空间就可以很好的规避这个问题。
从另一个方面来说,变长数组也有优点:栈上面分配空间和回收空间的速度要比堆上面的快,因为分配和回收空间只是指针的加减操作而已,但是堆上面的分配和回收就慢很多了。
变长结构体
变长结构体要把数组放在结构体的末尾,然后通过给变长结构体分配动态内存的时候可以额外的指定更多的空间用做buffer。值得注意的是,数组名是一个偏移量,本身不会占用空间,数组名代表的是一个不可修改的地址常量,但是我们对这个数组名指向的空间可以随意的指定。
(这里参考了 C++Q&A(二) 变长数组和变长结构体是什么)
二、问题
在录入数据时,VS编译器提示性报错:
C6385 从“BC”中读取的数据无效: 可读大小为“sizeof(Base_Context)+((contextcount+1))*sizeof(char)”个字节,但可能读取了“32”个字节。
C6386 写入到“BC”时缓冲区溢出: 可写大小为“sizeof(Base_Context)+((contextcount+1))*sizeof(char)”个字节,但可能写入了“32”个字节。
代码如下:
void AddResource(Base_Name* name, Base_Context* context)
{
//确认容量
//CheckResource(pc);
printf("变长数组调试,暂停加载确认容量\n");
//结构体临时内容
int contextcount = 0;
char context_paragraph[TEXT_1000] = { 0 };
//赋值
printf("请输入内容:\n");
scanf("%s", context_paragraph);
contextcount = strlen(context_paragraph);
char* contextpoint = context_paragraph;
--------------------重点--------------------
Base_Context* BC = malloc(sizeof(Base_Context) + (contextcount + 1) * sizeof(char));
if (BC == NULL && sizeof(BC) != 0)
{
perror("malloc/Base_Context* BC ");
return;
}
int BC_sz = 1;//确定数组位置
//strcpy(BC[BC->sz].context_paragraph, contextpoint);
memcpy(BC[BC_sz].context_paragraph, contextpoint, contextcount);
--------------------重点--------------------
BC[BC_sz].sz = BC_sz;
context = BC;
free(BC);
printf(" ----------------------------- \n");
printf(" | 成功录入,3秒后自动返回 | \n");
printf(" ----------------------------- \n");
Sleep(3000);
}
解决
C6385
查阅相关资料,首先怀疑的是strcpy在读取时超出了函数容量,导致内存溢出。(strcpy函数处理溢出的建议)如果是strcpy原因,则应该使用memcpy,确定读取字符的数量。
但测试后,确定不是strcpy原因,后又怀疑是BC开辟空间为0,不能写入,于是加入BC 指针判断,为NULL和指向空间为0时报错,但确定不是这个原因。
由于需要在给BC赋值时添加数组下标,确定数组位置。恰逢VS报错时提示空间为0,便将指针修改为0,再次运行,问题解决。
C6386
该问题与C6385连带出现,当修改了数组位置时,问题同时解决,原因就是指针指向空间与预想指向的空间不一致。