使用带map容器的struct结构体指针引发的段错误

本文探讨了在C++中使用包含容器如vector和map的结构体时可能遇到的问题及解决办法,特别是针对内存分配和初始化的具体实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 近期在使用结构体指针时遇到段错误,虽然最后解决了,但是有必要在此记录各种坑和解决方案。

1. 结构体指针没有初始化:

#include <map>
#include <iostream>
#include <unistd.h>
#include <vector>


using namespace std;

struct node
{
	int id;
	float length;
	vector<int> passwords;
	struct node *next;
};

int main(int argc, char **argv)
{
    struct node *n;
    
    n->id =1;
    n->length=1.24;
    n->passwords.push_back(1);
    n->passwords.push_back(2);
    n->passwords.push_back(3);
    n->next = NULL;
    
    printf("sizeof(struct node) = %d\n",sizeof(struct node));
    printf("sizeof(int) = %d\n",sizeof(int));
    printf("sizeof(float) = %d\n",sizeof(float));
    printf("sizeof(vector<int>) = %d\n",sizeof(vector<int>));
    printf("sizeof(struct node*) = %d\n",sizeof(struct node*));
    
    printf("n addr = %p\n",n);
    printf("n->id addr = %p\n",&(n->id));
    printf("n->length addr = %p\n",&(n->length));
    printf("n->passwords addr = %p\n",&(n->passwords));
    printf("n->next addr = %p\n",&(n->next));
     
    
    return 0;
}

代码执行后,报段错误,什么输出都灭有!

这个好解决,是因为指针n为随机值,灭有进行初始化。增加n = (struct node *)malloc(sizeof(struct node));即可。

2.  struct中有vector这种结构

#include <map>
#include <iostream>
#include <unistd.h>
#include <vector>


using namespace std;

struct node
{
	int id;
	float length;
	vector<int> passwords;
	struct node *next;
};

int main(int argc, char **argv)
{
    struct node *n = ( struct node *)malloc(sizeof( struct node));
    
    n->id =1;
    n->length=1.24;
    n->passwords.push_back(1);
    n->passwords.push_back(2);
    n->passwords.push_back(3);
    n->next = NULL;
    
    printf("sizeof(struct node) = %d\n",sizeof(struct node));
    printf("sizeof(int) = %d\n",sizeof(int));
    printf("sizeof(float) = %d\n",sizeof(float));
    printf("sizeof(vector<int>) = %d\n",sizeof(vector<int>));
    printf("sizeof(struct node*) = %d\n",sizeof(struct node*));
    
    printf("n addr = %p\n",n);
    printf("n->id addr = %p\n",&(n->id));
    printf("n->length addr = %p\n",&(n->length));
    printf("n->passwords addr = %p\n",&(n->passwords));
    printf("n->next addr = %p\n",&(n->next));
     
    
    return 0;
}

 说明struct中带了vector这种容器时,我们使用malloc对结构体对象指针进行初始化是没有问题的。

更进一步,我们发现sizeof(vector<int>>)的大小为24,这个就有点意思了,实际上跟插入vector的数据量无关。我们打印一下vector的各项地址:

#include <map>
#include <iostream>
#include <unistd.h>
#include <vector>


using namespace std;

struct node
{
	int id;
	float length;
	vector<int> passwords;
	struct node *next;
};

int main(int argc, char **argv)
{
    struct node *n=(struct node*)malloc(sizeof(struct node));
    
    n->id =1;
    n->length=1.24;
    n->passwords.push_back(1);
    n->passwords.push_back(2);
    n->passwords.push_back(3);
    n->passwords.push_back(4);
    n->passwords.push_back(5);
    n->passwords.push_back(6);
    n->passwords.push_back(7);
    n->passwords.push_back(8);
    n->passwords.push_back(9);
    n->next = NULL;
    
    printf("sizeof(struct node) = %d\n",sizeof(struct node));
    printf("sizeof(int) = %d\n",sizeof(int));
    printf("sizeof(float) = %d\n",sizeof(float));
    printf("sizeof(vector<int>) = %d\n",sizeof(vector<int>));
    printf("sizeof(struct node*) = %d\n",sizeof(struct node*));
    
    printf("n addr = %p\n",n);
    printf("n->id addr = %p\n",&(n->id));
    printf("n->length addr = %p\n",&(n->length));
    printf("n->passwords addr = %p\n",&(n->passwords));
    printf("n->next addr = %p\n",&(n->next));
     
    for(int i=0;i<24;i++)
    {
      printf("%02X ",*(((unsigned char *)(&(n->passwords)))+i));
    }
    for(int i=0;i<9;i++)
    {
      printf("n->passwords[%d] addr = %p\n",i,&((n->passwords[i])));
    }
    return 0;
}

这里可以看到struct中给vector<int>申请的24个字节,存储了3个值。经过多次验证,可以确定分别为vector的首地址(第一个元素的地址),下一个插入的地址,和将来vector进行扩展时的地址(当vector的下一个插入地址达到了未来扩展地址,则vector会再申请一段空间来用)。

经过多次验证,确定在struct中使用vector并没有什么问题。

3.  struct中有map这种结构

#include <map>
#include <iostream>
#include <unistd.h>
#include <vector>


using namespace std;

struct node
{
	int id;
	float length;
	vector<int> passwords;
	map<std::string,int> amap;
	struct node *next;
};

int main(int argc, char **argv)
{
    struct node *n=(struct node*)malloc(sizeof(struct node));
    
    n->id =1;
    n->length=1.24;
    n->passwords.push_back(1);
    n->passwords.push_back(2);
    n->passwords.push_back(3);
    n->passwords.push_back(4);
    n->passwords.push_back(5);
    n->passwords.push_back(6);
    n->passwords.push_back(7);
    n->passwords.push_back(8);
    n->passwords.push_back(9);
    n->next = NULL;
    
    printf("sizeof(struct node) = %d\n",sizeof(struct node));
    printf("sizeof(int) = %d\n",sizeof(int));
    printf("sizeof(float) = %d\n",sizeof(float));
    printf("sizeof(vector<int>) = %d\n",sizeof(vector<int>));
    printf("sizeof(map<std::string,int>) = %d\n",sizeof(map<std::string,int>));
    printf("sizeof(struct node*) = %d\n",sizeof(struct node*));
    
    printf("n addr = %p\n",n);
    printf("n->id addr = %p\n",&(n->id));
    printf("n->length addr = %p\n",&(n->length));
    printf("n->passwords addr = %p\n",&(n->passwords));
    printf("n->next addr = %p\n",&(n->next));
    printf("n->amap addr = %p\n",&(n->amap));
     
    for(int i=0;i<24;i++)
    {
      printf("%02X ",*(((unsigned char *)(&(n->passwords)))+i));
    }
    for(int i=0;i<9;i++)
    {
      printf("n->passwords[%d] addr = %p\n",i,&((n->passwords[i])));
    }
    
    n->amap.insert(std::make_pair("123",1));
    printf("insert key/value finished!\n");
    return 0;
}

发现,sizeof(map<std::string,int>)为48字节,估计和vector的情形一致。但是后续的插入失败。我们想着前面我已经为node申请空间了,并且n->amap是有地址的,为什么还无法插入呢?我们把这48个字节打印出来:

#include <map>
#include <iostream>
#include <unistd.h>
#include <vector>


using namespace std;

struct node
{
	int id;
	float length;
	vector<int> passwords;
	map<std::string,int> amap;
	struct node *next;
};

int main(int argc, char **argv)
{
    struct node *n=(struct node*)malloc(sizeof(struct node));
    
    n->id =1;
    n->length=1.24;
    n->passwords.push_back(1);
    n->passwords.push_back(2);
    n->passwords.push_back(3);
    n->passwords.push_back(4);
    n->passwords.push_back(5);
    n->passwords.push_back(6);
    n->passwords.push_back(7);
    n->passwords.push_back(8);
    n->passwords.push_back(9);
    n->next = NULL;
    
    printf("sizeof(struct node) = %d\n",sizeof(struct node));
    printf("sizeof(int) = %d\n",sizeof(int));
    printf("sizeof(float) = %d\n",sizeof(float));
    printf("sizeof(vector<int>) = %d\n",sizeof(vector<int>));
    printf("sizeof(map<std::string,int>) = %d\n",sizeof(map<std::string,int>));
    printf("sizeof(struct node*) = %d\n",sizeof(struct node*));
    
    printf("n addr = %p\n",n);
    printf("n->id addr = %p\n",&(n->id));
    printf("n->length addr = %p\n",&(n->length));
    printf("n->passwords addr = %p\n",&(n->passwords));
    printf("n->next addr = %p\n",&(n->next));
    printf("n->amap addr = %p\n",&(n->amap));
    
    
    
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*******************\n");
    
    for(int i=0;i<24;i++)
    {
      printf("%02X ",*(((unsigned char *)(&(n->passwords)))+i));
    }
    for(int i=0;i<9;i++)
    {
      printf("n->passwords[%d] addr = %p\n",i,&((n->passwords[i])));
    }
    
    n->amap.insert(std::make_pair("123",1));
    printf("insert key/value finished!\n");
    return 0;
}

发现map所占的48个字节全是0,如果真的是和vector相似,那么后面往0这个地址插入内容,肯定出错。

#include <map>
#include <iostream>
#include <unistd.h>
#include <vector>


using namespace std;

struct node
{
	int id;
	float length;
	vector<int> passwords;
	map<std::string,int> amap;
	struct node *next;
};

int main(int argc, char **argv)
{
    struct node *n=(struct node*)malloc(sizeof(struct node));
    
    n->id =1;
    n->length=1.24;
    n->passwords.push_back(1);
    n->passwords.push_back(2);
    n->passwords.push_back(3);
    n->passwords.push_back(4);
    n->passwords.push_back(5);
    n->passwords.push_back(6);
    n->passwords.push_back(7);
    n->passwords.push_back(8);
    n->passwords.push_back(9);
    n->next = NULL;
    
    printf("sizeof(struct node) = %d\n",sizeof(struct node));
    printf("sizeof(int) = %d\n",sizeof(int));
    printf("sizeof(float) = %d\n",sizeof(float));
    printf("sizeof(vector<int>) = %d\n",sizeof(vector<int>));
    printf("sizeof(map<std::string,int>) = %d\n",sizeof(map<std::string,int>));
    printf("sizeof(struct node*) = %d\n",sizeof(struct node*));
    
    printf("n addr = %p\n",n);
    printf("n->id addr = %p\n",&(n->id));
    printf("n->length addr = %p\n",&(n->length));
    printf("n->passwords addr = %p\n",&(n->passwords));
    printf("n->next addr = %p\n",&(n->next));
    printf("n->amap addr = %p\n",&(n->amap));
    
    
    
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*******************\n");
    
    for(int i=0;i<24;i++)
    {
      printf("%02X ",*(((unsigned char *)(&(n->passwords)))+i));
    }
    for(int i=0;i<9;i++)
    {
      printf("n->passwords[%d] addr = %p\n",i,&((n->passwords[i])));
    }
    
    std::map<std::string,int> tmpMap;
    
    tmpMap.insert(std::make_pair("123",1));
    
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(tmpMap)))+i));
    }
    printf("----------------------\n");
    
    n->amap = tmpMap;
    
    printf("insert key/value finished!\n");
     
     for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(tmpMap)))+i));
    }
    printf("+++++++++++++++++++++\n");
    
     for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*******************\n");
    
    printf("n->amap[\"123\"]=%d\n",n->amap["123"]);
    n->amap["234"]=2;
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*=========================\n");
    printf("n->amap[\"234\"]=%d\n",n->amap["234"]);
    
    n->amap.insert(std::make_pair("345",3));
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("||||||||||||||||||||||\n");
    
    printf("n->amap[\"345\"]=%d\n",n->amap["345"]);
    return 0;
}

通过上述结果,我们发现,只要将n->amap进行了初始化(先将一个临时map赋值,然后将内容给它),后面就可以使用各种方式进行插入。

#include <map>
#include <iostream>
#include <unistd.h>
#include <vector>


using namespace std;

struct node
{
	int id;
	float length;
	vector<int> passwords;
	map<std::string,int> amap;
	struct node *next;
};

int main(int argc, char **argv)
{
    struct node *n=(struct node*)malloc(sizeof(struct node));
    
    n->id =1;
    n->length=1.24;
    n->passwords.push_back(1);
    n->passwords.push_back(2);
    n->passwords.push_back(3);
    n->passwords.push_back(4);
    n->passwords.push_back(5);
    n->passwords.push_back(6);
    n->passwords.push_back(7);
    n->passwords.push_back(8);
    n->passwords.push_back(9);
    n->next = NULL;
    
    printf("sizeof(struct node) = %d\n",sizeof(struct node));
    printf("sizeof(int) = %d\n",sizeof(int));
    printf("sizeof(float) = %d\n",sizeof(float));
    printf("sizeof(vector<int>) = %d\n",sizeof(vector<int>));
    printf("sizeof(map<std::string,int>) = %d\n",sizeof(map<std::string,int>));
    printf("sizeof(struct node*) = %d\n",sizeof(struct node*));
    
    printf("n addr = %p\n",n);
    printf("n->id addr = %p\n",&(n->id));
    printf("n->length addr = %p\n",&(n->length));
    printf("n->passwords addr = %p\n",&(n->passwords));
    printf("n->next addr = %p\n",&(n->next));
    printf("n->amap addr = %p\n",&(n->amap));
    
    
    
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*******************\n");
    
    for(int i=0;i<24;i++)
    {
      printf("%02X ",*(((unsigned char *)(&(n->passwords)))+i));
    }
    for(int i=0;i<9;i++)
    {
      printf("n->passwords[%d] addr = %p\n",i,&((n->passwords[i])));
    }
    
    std::map<std::string,int> tmpMap;
    std::map<std::string,int> *tmpMap2 =(std::map<std::string,int>*)malloc(sizeof(std::map<std::string,int>));
    printf("malloc a map!\n");
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)tmpMap2)+i));
    }
    printf("xxxxxxxxxxxxxxxxxxxx\n");
    tmpMap2->insert(std::make_pair("123",1));
    printf("malloc and insert to map!\n");
    
    tmpMap.insert(std::make_pair("123",1));
    
    /*tmpMap2 = &tmpMap;
     for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)tmpMap2)+i));
    }
    printf("yyyyyyyyyyyyyyyyyyyy\n");
    */
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(tmpMap)))+i));
    }
    printf("----------------------\n");
    
    n->amap = tmpMap;
    
    printf("insert key/value finished!\n");
     
     for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(tmpMap)))+i));
    }
    printf("+++++++++++++++++++++\n");
    
     for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*******************\n");
    
    printf("n->amap[\"123\"]=%d\n",n->amap["123"]);
    n->amap["234"]=2;
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*=========================\n");
    printf("n->amap[\"234\"]=%d\n",n->amap["234"]);
    
    n->amap.insert(std::make_pair("345",3));
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("||||||||||||||||||||||\n");
    
    printf("n->amap[\"345\"]=%d\n",n->amap["345"]);
    return 0;
}

上述,我们将map进行了malloc,然后调用insert函数,也是出现段错误。

 这说明无论哪种情况,map的指针即使malloc申请了地址,也无法使用insert函数进行插入。如果把map指针指向一个具体的map,就可以使用。

而对于结构体中的map,我们只能把它当作一个没有初始化的map(或者说,并没有给它开辟空间)。

#include <map>
#include <iostream>
#include <unistd.h>
#include <vector>


using namespace std;

struct node
{
	int id;
	float length;
	vector<int> passwords;
	map<std::string,int> amap;
	struct node *next;
};

int main(int argc, char **argv)
{
    struct node *n=(struct node*)malloc(sizeof(struct node));
    
    n->id =1;
    n->length=1.24;
    n->passwords.push_back(1);
    n->passwords.push_back(2);
    n->passwords.push_back(3);
    n->passwords.push_back(4);
    n->passwords.push_back(5);
    n->passwords.push_back(6);
    n->passwords.push_back(7);
    n->passwords.push_back(8);
    n->passwords.push_back(9);
    n->next = NULL;
    
    printf("sizeof(struct node) = %d\n",sizeof(struct node));
    printf("sizeof(int) = %d\n",sizeof(int));
    printf("sizeof(float) = %d\n",sizeof(float));
    printf("sizeof(vector<int>) = %d\n",sizeof(vector<int>));
    printf("sizeof(map<std::string,int>) = %d\n",sizeof(map<std::string,int>));
    printf("sizeof(struct node*) = %d\n",sizeof(struct node*));
    
    printf("n addr = %p\n",n);
    printf("n->id addr = %p\n",&(n->id));
    printf("n->length addr = %p\n",&(n->length));
    printf("n->passwords addr = %p\n",&(n->passwords));
    printf("n->next addr = %p\n",&(n->next));
    printf("n->amap addr = %p\n",&(n->amap));
    
    
    
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*******************\n");
    
    for(int i=0;i<24;i++)
    {
      printf("%02X ",*(((unsigned char *)(&(n->passwords)))+i));
    }
    for(int i=0;i<9;i++)
    {
      printf("n->passwords[%d] addr = %p\n",i,&((n->passwords[i])));
    }
    
    std::map<std::string,int> tmpMap;
    std::map<std::string,int> *tmpMap2 =(std::map<std::string,int>*)malloc(sizeof(std::map<std::string,int>));
    printf("malloc a map!\n");
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)tmpMap2)+i));
    }
    printf("xxxxxxxxxxxxxxxxxxxx\n");
   // tmpMap2->insert(std::make_pair("123",1));
    //printf("malloc and insert to map!\n");
    
    tmpMap.insert(std::make_pair("123",1));
    
    tmpMap2 = &tmpMap;
     for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)tmpMap2)+i));
    }
    printf("yyyyyyyyyyyyyyyyyyyy\n");
    
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(tmpMap)))+i));
    }
    printf("----------------------\n");
    
    n->amap = tmpMap;
    
    printf("insert key/value finished!\n");
     
     for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(tmpMap)))+i));
    }
    printf("+++++++++++++++++++++\n");
    
     for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*******************\n");
    
    printf("n->amap[\"123\"]=%d\n",n->amap["123"]);
    n->amap["234"]=2;
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("*=========================\n");
    printf("n->amap[\"234\"]=%d\n",n->amap["234"]);
    
    n->amap.insert(std::make_pair("345",3));
    for(int i=0;i<48;i++)
    {
     printf("%02X ",*(((unsigned char *)(&(n->amap)))+i));
    }
    printf("||||||||||||||||||||||\n");
    
    printf("n->amap[\"345\"]=%d\n",n->amap["345"]);
    return 0;
}

即使把结构体中的amap改成指针,上述问题同样存在。

结论:struct中如果有map容器,则一定要用一个临时map对struct中的map赋值,然后才可以直接使用struct中的map。否则会出现段错误。具体深层次原因,待解!!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值