OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6599|回复: 27

结构体作为函数参数调用的问题

[复制链接]

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
发表于 2021-4-22 15:54:05 | 显示全部楼层 |阅读模式
20金钱
首先是定义的结构体
struct individual
                      {    double  gene[a];                    /* 染色体 */
                        double  fitness;                   /* 个体适应度*/
                       double selectprob;
                       double sumprob;
                       };
struct individual pop[popsize+1];
然后是在Ag_Init()这个函数里调用ag_adopt函数,其中ag_adopt定义为double ag_adopt(double *p,double *m,double *n)        ,不知道为什么这样不可以,一硬件仿真就会进入直接进入 void HardFault_Handler(void) ,有没有大佬会这个啊!
void Ag_Init(void)
{
    int ag_index=0;
    double max_fit = 0;
          double *pt,*mt,*nt;
          initialize();
    for(int i = 0; i < eranum; i++)
    {
        for(int j = 0; j < popsize; j++)
        {
                                           *pt=pop[j].gene[0];
                   *mt=pop[j].gene[1];
                   *nt=pop[j].gene[2];
            pop[j].fitness =  ag_adopt(pt,mt,nt);
            if(pop[j].fitness >= max_fit)
            {
                max_fit = pop[j].fitness;
                ag_index = j;
            }
        }
}

最佳答案

查看完整内容[请看2#楼]

感谢大家的帮助,问题已解决,除了指针的问题,还有数组的问题,数组的定义是没有问题的,因为我之前定义了两个6500的数组,加上遗传算法的迭代,导致数组溢出
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 15:54:06 | 显示全部楼层
本帖最后由 暮二木 于 2021-4-23 15:43 编辑

感谢大家的帮助,问题已解决,除了指针的问题,还有数组的问题,数组的定义是没有问题的,因为我之前定义了两个6500的数组,加上遗传算法的迭代,导致数组溢出
回复

使用道具 举报

3

主题

15

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
290
金钱
290
注册时间
2021-1-8
在线时间
39 小时
发表于 2021-4-22 16:15:31 | 显示全部楼层
a是宏?
回复

使用道具 举报

12

主题

3389

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8645
金钱
8645
注册时间
2020-5-11
在线时间
4102 小时
发表于 2021-4-22 16:18:28 | 显示全部楼层
本帖最后由 LcwSwust 于 2021-4-22 16:23 编辑

你的问题在于:指针未初始化,不知指向何方,却对其指向的地方赋值。
这帖子第13条
http://www.openedv.com/forum.php?mod=viewthread&tid=323935&extra=

专治疑难杂症
回复

使用道具 举报

18

主题

151

帖子

0

精华

高级会员

Rank: 4

积分
508
金钱
508
注册时间
2020-4-22
在线时间
241 小时
发表于 2021-4-22 16:19:36 | 显示全部楼层
一步一步调试,看从什么地方进入的HardFault_Handler
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 16:21:21 | 显示全部楼层

是的,#define a 3
#define popsize 50
#define eranum 25
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 16:36:37 | 显示全部楼层
LcwSwust 发表于 2021-4-22 16:18
你的问题在于:指针未初始化,不知指向何方,却对其指向的地方赋值。
这帖子第13条
http://www.openedv.c ...

  double *pt,*mt,*nt,l,m,n;
          pt=&l;
          mt=&m;
          nt=&n;
//          initialize();
    for(int i = 0; i < eranum; i++)
    {
        for(int j = 0; j < popsize; j++)
        {
                                            *pt=pop[j].gene[0];
                    *mt=pop[j].gene[1];
                    *nt=pop[j].gene[2];
           pop[j].fitness =  ag_adopt(l,m,n);
你好,我改了一下,这样还是不对啊
回复

使用道具 举报

2

主题

459

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4478
金钱
4478
注册时间
2018-5-14
在线时间
959 小时
发表于 2021-4-22 17:01:26 | 显示全部楼层
*pt这个指针没有给地址,或者是*pt=pop[j].gene[1]的方法有错,因为pt在你定义的时候只是指针而没分配地址,给未分配地址的指针赋值导致内存非法访问,
第一种方式:应该是pt=&pop[j].gene[1];这样pt就有实际的地址了,pt指向gene【1】。
第二种方式:在定义*pt后加入,pt=(double *)malloc(sizeof(double);这样pt有了新的空间,然后*pt=pop[j].gene[1]是正确的;使用完记得free。

第一种方式 pt其实是gene的镜像,操作pt会导致gene发生改变,第二种方法操作pt不会影响gene的变化,因为是两个不同的内存单元了。
用指针首先要分清哪个是地址,哪个是值。
回复

使用道具 举报

24

主题

119

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2590
金钱
2590
注册时间
2017-4-4
在线时间
341 小时
发表于 2021-4-22 17:43:15 | 显示全部楼层
姚先起 发表于 2021-4-22 17:01
*pt这个指针没有给地址,或者是*pt=pop[j].gene[1]的方法有错,因为pt在你定义的时候只是指针而没分配地址 ...

你写的多,就感觉你是正确的。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2021-4-22 17:49:06 | 显示全部楼层
*pt=pop[j].gene[0];
*mt=pop[j].gene[1];
*nt=pop[j].gene[2];

应该是

pt=&(pop[j].gene[0]);
mt=&(pop[j].gene[1]);
nt=&(pop[j].gene[2]);


回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 17:56:31 | 显示全部楼层
edmund1234 发表于 2021-4-22 17:49
*pt=pop[j].gene[0];
*mt=pop[j].gene[1];
*nt=pop[j].gene[2];

谢谢,就感觉很奇怪,我确实是这么写的,但还是在硬件调试的时候进入void HardFault_Handler(void),然后把指针删掉就不会进入
void Ag_Init(void)
{
    int ag_index=0;
    double max_fit = 0;
          double *pt,*mt,*nt;
         
//          initialize();
    for(int i = 0; i < eranum; i++)
    {
        for(int j = 0; j < popsize; j++)
        {
                                            pt=&pop[j].gene[0];
                    mt=&pop[j].gene[1];
                    nt=&pop[j].gene[2];
//              pop[j].fitness =  ag_adopt(pt,mt,nt);
//            if(pop[j].fitness >= max_fit)
//            {
//                max_fit = pop[j].fitness;
//                ag_index = j;
//            }
        }
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 17:58:05 | 显示全部楼层
姚先起 发表于 2021-4-22 17:01
*pt这个指针没有给地址,或者是*pt=pop[j].gene[1]的方法有错,因为pt在你定义的时候只是指针而没分配地址 ...

谢谢,但是如果用的keil的话应该不能用malloc动态分配地址吧,用第一种方法也还是会进入void HardFault_Handler(void)
回复

使用道具 举报

18

主题

151

帖子

0

精华

高级会员

Rank: 4

积分
508
金钱
508
注册时间
2020-4-22
在线时间
241 小时
发表于 2021-4-22 18:05:53 | 显示全部楼层
暮二木 发表于 2021-4-22 17:56
谢谢,就感觉很奇怪,我确实是这么写的,但还是在硬件调试的时候进入void HardFault_Handler(void),然后 ...

楼主有用吗?第一种写法,好像是给指向的内容赋值?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2021-4-22 18:20:46 | 显示全部楼层
本帖最后由 edmund1234 于 2021-4-22 18:21 编辑
暮二木 发表于 2021-4-22 17:56
谢谢,就感觉很奇怪,我确实是这么写的,但还是在硬件调试的时候进入void HardFault_Handler(void),然后 ...

如果说, 你这样屏蔽了就不进HardFault_Handler, 那问题是在ag_adopt函数内
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2021-4-22 18:33:38 | 显示全部楼层
暮二木 发表于 2021-4-22 17:56
谢谢,就感觉很奇怪,我确实是这么写的,但还是在硬件调试的时候进入void HardFault_Handler(void),然后 ...

在HardFault_Handler 设个断点, 在断点停下来后, 在寄存器窗口, 把SP的值抄出来

然后把此地址贴到Memory窗口



然后在这窗口, 右键 选 Show Disassembler At Address。。。


然后把第七个INT抄出来的值贴上, 就可以看到是那一句触发HardFault异常

回复

使用道具 举报

6

主题

211

帖子

0

精华

高级会员

Rank: 4

积分
833
金钱
833
注册时间
2019-12-17
在线时间
157 小时
发表于 2021-4-22 18:38:18 | 显示全部楼层
你指针赋值不对
void Ag_Init(void)
{
    int ag_index=0;
    double max_fit = 0;
          double *pt,*mt,*nt;//这里没有初始化
          initialize();
    for(int i = 0; i < eranum; i++)
    {
        for(int j = 0; j < popsize; j++)
        {
                                           *pt=pop[j].gene[0];//这里你赋值的内容是gene[0]的值而不是所在的地址,后面两个同理,如果你想传递地址需要用取地址符&取出地址或者把gene数组名当作指针用 pop[j].gene[0]的地址就是 pop[j].gene ,pop[j].gene[1]的地址就是pop[j].gene + 1
                   *mt=pop[j].gene[1];
                   *nt=pop[j].gene[2];
            pop[j].fitness =  ag_adopt(pt,mt,nt);
            if(pop[j].fitness >= max_fit)
            {
                max_fit = pop[j].fitness;
                ag_index = j;
            }
        }
}
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 19:51:16 | 显示全部楼层
edmund1234 发表于 2021-4-22 18:20
如果说, 你这样屏蔽了就不进HardFault_Handler, 那问题是在ag_adopt函数内

不是,是把指针屏蔽了不进去HardFault_Handler,把ag_adopt屏蔽了没有影响
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 19:53:16 | 显示全部楼层
moranyidui 发表于 2021-4-22 18:05
楼主有用吗?第一种写法,好像是给指向的内容赋值?

第一种应该是指向pop[j].gene的地址吧,我觉得哈
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 20:08:17 | 显示全部楼层
y284858 发表于 2021-4-22 18:38
你指针赋值不对
void Ag_Init(void)
{

谢谢,其实地址和值都行,我主要是想把pop[j].gene[]传给ag_adopt,但是传的都不对
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-22 20:38:56 | 显示全部楼层
edmund1234 发表于 2021-4-22 18:33
在HardFault_Handler 设个断点, 在断点停下来后, 在寄存器窗口, 把SP的值抄出来

然后把此地址贴到M ...

谢谢大佬,虽然你贴的图看不见,但是我试了一下,就是我硬件仿真时一进去就是全速运行,然后此时加断点,不管加到哪里都不会停止,然后停止仿真后才会到HardFault_Handler,就很奇怪,但是删掉指针就不会这样。

1.rar

3.56 MB, 下载次数: 2

回复

使用道具 举报

2

主题

459

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4478
金钱
4478
注册时间
2018-5-14
在线时间
959 小时
发表于 2021-4-23 08:46:14 | 显示全部楼层
暮二木 发表于 2021-4-22 17:58
谢谢,但是如果用的keil的话应该不能用malloc动态分配地址吧,用第一种方法也还是会进入void HardFault_H ...

那你试试注释掉ag_adopt,看看还会不会异常。
回复

使用道具 举报

18

主题

151

帖子

0

精华

高级会员

Rank: 4

积分
508
金钱
508
注册时间
2020-4-22
在线时间
241 小时
发表于 2021-4-23 09:11:41 | 显示全部楼层
暮二木 发表于 2021-4-22 20:38
谢谢大佬,虽然你贴的图看不见,但是我试了一下,就是我硬件仿真时一进去就是全速运行,然后此时加断点, ...

断点从第一行打起,再运行
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-23 10:17:47 | 显示全部楼层
moranyidui 发表于 2021-4-23 09:11
断点从第一行打起,再运行

有点问题
1.png
回复

使用道具 举报

6

主题

211

帖子

0

精华

高级会员

Rank: 4

积分
833
金钱
833
注册时间
2019-12-17
在线时间
157 小时
发表于 2021-4-23 11:40:42 | 显示全部楼层
本帖最后由 y284858 于 2021-4-23 11:49 编辑
暮二木 发表于 2021-4-22 20:08
谢谢,其实地址和值都行,我主要是想把pop[j].gene[]传给ag_adopt,但是传的都不对

你传的是值但是在函数里面是把这个值当作指针来用,结果就会造成非法访问进入硬件错误中断你把这三句
*pt=pop[j].gene[0];
                   *mt=pop[j].gene[1];//编辑补充说明:之前没有注意你的指针变量名前面有*,你的指针还没有初始化地址,你的目的是把后面地址赋值给指针变量,那么你应当直接使用指针变量名,如果在变量名前加入*就是对指针指向的地址进行操作。你需要复习一下关于指针的知识了
                   *nt=pop[j].gene[2];

改成
pt=pop[j].gene ;
                   mt=pop[j].gene+1;
                   nt=pop[j].gene+2;
试试
回复

使用道具 举报

0

主题

54

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
272
金钱
272
注册时间
2019-3-6
在线时间
36 小时
发表于 2021-4-23 12:24:32 | 显示全部楼层
这属于最基本的编码能力范畴


首先double ag_adopt(double *p,double *m,double *n)函数中,ag_adopt函数是否要修改3个形参?如果不需要,请不要随便定义成指针。( 看你后面的代码,这里很可能是不需要的 )直接定义双精度对象就足够了。


其次,之前的朋友也说了*pt,*mt,*nt这三个指针定义后没有初始化,就直接间接引用赋值了。这等于对三个野指针的内容进行赋值,这是不对的。

再次,如果ag_adopt函数的形参一定要定义为指针,调用的时候直接填对应数组的地址就可以了,根本不需要先定义三个指针赋值完了后再填入形参,多此一举!
类似于这样 pop[j].fitness = ag_adopt( &( pop[j].gene[0] ), &( pop[j].gene[1] ), &( pop[j].gene[2] ) );



最后,新手上路,不要随便乱用指针,定义了指针后一定要初始化,调用指针之前一定要断言判断指针是否合法。
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-23 13:04:58 | 显示全部楼层
y284858 发表于 2021-4-23 11:40
你传的是值但是在函数里面是把这个值当作指针来用,结果就会造成非法访问进入硬件错误中断你把这三句
*p ...

好的谢谢,我试一下
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-23 13:05:48 | 显示全部楼层
本帖最后由 暮二木 于 2021-4-23 13:07 编辑
QuiGonJinn 发表于 2021-4-23 12:24
这属于最基本的编码能力范畴

嗯嗯谢谢,感谢指导
回复

使用道具 举报

14

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
213
金钱
213
注册时间
2020-7-3
在线时间
71 小时
 楼主| 发表于 2021-4-23 13:26:21 | 显示全部楼层
姚先起 发表于 2021-4-23 08:46
那你试试注释掉ag_adopt,看看还会不会异常。

感谢各位大佬,指针我注释掉了,但是我前面观察的不够仔细,今天我发现把结构体注释掉就不会有异常,但我觉得我结构体没有问题啊typedef struct
{
    double  gene[chro];                    /* 染色体 */
    double  fitness;                   /* 个体适应度*/
    double selectprob;
    double sumprob;
}individual;

individual pop[popsize];
individual newpop[popsize];
individual bestpop[eranum];
调用是pop.gene[]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-25 04:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表