C语言中遇到的一个栈和堆的问题
C中一个异常挂死,捣腾了大半天。先记录下来。因为是公司代码帖出来不太适合。精简之。主要讲述问题。
好了现在讲述问题,主要遇到的问题是C 语言中,char p[] 这种不定长数组的应用。
typedef struct
{
int8_ file_path[64];
}file_path_t;
typedef struct
{
uint8_ delete_all;
file_path_t file[]; // =========================>如这里,设计思想是可以传N个长度的file_path_t类型数组。这个file[]根据实际需要来决定。
}file_delete_req_t;
而在实际应用中,我们如果理解错误会遇到跟我一样的问题。如下:
void send_net_pack_file_delete_req(int socketfd)
{
unsigned char cmd[1024];
int i = 0;
msg_head_t Msghead; //注意变量是在栈上
file_delete_req_t file_delete_req; //注意变量是在栈上
memset(&Msghead, 0, sizeof(msg_head_t));
memset(&file_delete_req, 0, sizeof(file_delete_req_t));
file_delete_req.delete_all = 1;
strncpy(file_delete_req.file[0].file_path, "d:\\show\\log", sizeof("d:\\show\\log"));
net_pack_file_delete_req(Msghead, file_delete_req);
return;
}
红色部分,表面上看起来是没有问题。
msg_head_t Msghead;
file_delete_req_t file_delete_req;
一个结构体类型的变量我们随处可以。
我先把完整代码帖出来。
///////////////////////////////////////////begin/////////////////////////////////////////////////////
#include <stdio.h>
typedef signed char int8_;
typedef signed short int int16_;
typedef signed int int32_; //signed long
typedef signed long long int64_;
typedef unsigned char uint8_;
typedef unsigned short int uint16_;
typedef unsigned int uint32_; //unsigned long
typedef unsigned long long uint64_;
#define MSG_HEAD_MAGIC "begin"
typedef struct
{
int8_ file_path[64];
}file_path_t;
typedef struct
{
uint8_ delete_all;
file_path_t file[];
}file_delete_req_t;
typedef struct
{
int8_ magic[4];
uint8_ msg_type;
uint8_ cmd_class;
uint16_ cmd_id;
uint32_ data_len;
uint32_ version;
int8_ reserved[4];
}msg_head_t;
static int net_set_head(file_delete_req_t *req, msg_head_t *head, uint8_ msg_type, uint8_ cmd_class,
uint16_ cmd_id, uint32_ data_len)
{
int i = 0;
if(!head)
return -1;
file_path_t *file = (file_path_t *)((char*)req + sizeof(char));
printf("head->magic %s\n", head->magic);
printf("head->magic %x\n", head->msg_type);
printf("head->magic %x\n", head->cmd_class);
printf("head->magic %x\n", head->cmd_id);
printf("head->magic %x\n", head->data_len);
printf("head->magic %x\n", head->version);
memcpy((void*)head->magic, (const void*)MSG_HEAD_MAGIC, strlen(MSG_HEAD_MAGIC));
printf("head->magic %s\n", head->magic);
printf("%s, L:%d\n", file->file_path, __LINE__);
head->msg_type = msg_type;
printf("%s, L:%d\n", file->file_path, __LINE__);
head->cmd_class = cmd_class;
printf("%s, L:%d\n", file->file_path, __LINE__);
head->cmd_id = cmd_id;
printf("%s, L:%d\n", file->file_path, __LINE__);
head->data_len = data_len;
printf("%s, L:%d\n", file->file_path, __LINE__);
head->version = 0x010203;
printf("%s, L:%d\n", file->file_path, __LINE__);
printf("head->magic %s\n", head->magic);
printf("head->magic %x\n", head->msg_type);
printf("head->magic %x\n", head->cmd_class);
printf("head->magic %x\n", head->cmd_id);
printf("head->magic %x\n", head->data_len);
printf("head->magic %x\n", head->version);
return 0;
}
int net_pack_file_delete_req(msg_head_t *head, file_delete_req_t *req)
{
int i = 0;
int data_len = sizeof(req->file[0].file_path);
printf("data_len:%d req%x, head:%x\n", data_len, req, head);
net_set_head(req, head, 1, 2, 3, data_len);
return 0;
}
void send_net_pack_file_delete_req(int socketfd)
{
unsigned char cmd[1024];
int i = 0;
msg_head_t Msghead;
file_delete_req_t file_delete_req;
memset(&Msghead, 0, sizeof(msg_head_t));
memset(&file_delete_req, 0, sizeof(file_delete_req_t));
file_delete_req.delete_all = 1;
strncpy(file_delete_req.file[0].file_path, "d:\\show\\log", sizeof("d:\\show\\log"));
net_pack_file_delete_req(&Msghead, &file_delete_req);
return;
}
int main(void)
{
send_net_pack_file_delete_req(111);
return 0;
}
///////////////////////////////////////////end///////////////////////////////////////////////////////
运行结果:
有心人会发现,Msghead变量成功的将file_delete_req的内容给改变了。虽然我们在调用net_set_head()函数时,只是希望给Msghead变量填值。但确发现file_delete_req变量的内容也被改变了。归其原因还是栈的问题。
比喻我们做实验,改造一下send_net_pack_file_delete_req()函数。往file_delete_req和Msghead之间插入一个大的空间。一切数据又都正常。想不明白为什么会被采。
file_delete_req_t file_delete_req;
unsigned char cmd[1024];
msg_head_t Msghead;
void send_net_pack_file_delete_req(int socketfd)
{
int i = 0;
file_delete_req_t file_delete_req;
unsigned char cmd[1024];
msg_head_t Msghead;
memset(&Msghead, 0, sizeof(msg_head_t));
memset(&file_delete_req, 0, sizeof(file_delete_req_t));
file_delete_req.delete_all = 1;
strncpy(file_delete_req.file[0].file_path, "d:\\show\\log", sizeof("d:\\show\\log"));
net_pack_file_delete_req(&Msghead, &file_delete_req);
return;
}
解决办法就是用malloc申请一个“堆”给file_delete_req_t file_delete_req; msg_head_t Msghead;使用。