You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Malloc分配空间是否正确?ARM平台库函数修改结构体成员失效求助

结构体传参修改成员值失效问题排查

问题背景

遇到结构体传参后修改成员值的问题:示例项目中功能正常,但在Visual Studio Code环境下基于ARM Cortex M3和第三方库开发时功能失效,核心目标是修改结构体中的chip_count成员。

程序验证流程如下:创建特定结构体类型的指针,将该指针的地址传入函数,函数内部通过malloc申请新内存空间,将传入的指针指向该malloc分配的地址,修改该malloc空间中结构体的部分变量值,返回main函数后读取malloc空间的修改后内容,该逻辑本身已验证可行。

指针相关定义说明:vtss_state_t等价于struct vtss_state_s,vtss_inst_t是指向struct vtss_state_s(即vtss_state_t)的指针;vtss_create函数的参数为**vtss_inst_t const inst,即指向vtss_inst_t的指针,函数末尾将malloc返回的地址赋值给(*inst),即可让外部指针指向malloc分配的空间。

第一部分:在线编译器验证测试

先在在线编译器中验证修改传入结构体成员的逻辑,结果正常,相关代码如下:

FILE: state.h

#include <stdint.h>

/******************************************************************************
                           Structures
*******************************************************************************/

typedef struct tests
{
  int x;
} tests_t;


typedef uint32_t u32;

// This is the structure with  chip_count 
typedef struct vtss_state_s
{
  int a;
  int cookie;
  tests_t u;
  int port_count; 
  u32 chip_count; // doesnt change in my real program :(

} vtss_state_t;

// typedef this structure so vtss_inst_t points to it...(?)
typedef struct vtss_state_s *vtss_inst_t;

FILE: main.c

/*******************************************************************************
                                Online C Compiler.
                    Code, Compile, Run and Debug C program online.
    Write your code in this editor and press "Run" button to compile and execute it.
    *******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "state.h"
#define VTSS_PORT_COUNT 1
#define VTSS_PORTS VTSS_PORT_COUNT

// some global structure
vtss_inst_t testspace;
vtss_inst_t *testspace_ptr;

/******************************************************************************
                           functions
*******************************************************************************/

// vtss_inst_get ()
// const adress another access style 
void
vtss_inst_get (const vtss_inst_t inst)
{
  printf ("\ninst get()");
  printf ("\ninst get() adress of inst:%d", inst);
  inst->a = 1111;
}

// This function just should proof that it can change the content 

void
vtss_inst_default_set (vtss_state_t * vtss_state)
{
  vtss_state->port_count = VTSS_PORTS;  // 1
}


//** This is the function which should change "chip_count"
// Man soll einen Pointer auf einen Pointer auf die Struktur C<bergeben (wo sich chip_count befindet )
void
vtss_inst_create (vtss_inst_t * const inst)
{

  printf ("\r\n**vtss_inst_create()");
  vtss_state_t *vtss_state; // temporary pointer  ( just points to a structure )
  vtss_state_t *vtss_state_2;   // just a test compare
  // pass temporary pointer a new memory space:
  vtss_state = malloc (sizeof (*vtss_state));   // is this correct? anyway it also doesnt work without this malloc style
  printf ("\r\n\t malloc=: %d", vtss_state);
  // pass test temporary pointer a new memory space:
  vtss_state_2 = malloc (sizeof (*vtss_state_2));
  printf ("\r\n\t (test) malloc2: %d", vtss_state_2);
  //Test: pass the temporary pointer even deeper & change content of structure where it points to 
  // (change variable port_count to 1)
  vtss_inst_default_set (vtss_state);
  vtss_inst_default_set (vtss_state_2);
  //Test:Change values of the structure:
  vtss_state->a = 1;
  vtss_state->chip_count = 12121;
  vtss_state_2->chip_count = 12121;
  // ** Giving back the new adress from malloc:
  // Test:(from vtss_state or vtss_state2)
  (*inst) = vtss_state;     //passing adress1
  //Test: a should have the correct value:
  printf ("\r\n\ta=1? a =%d ", (*inst)->a);
  (*inst) = vtss_state_2;   //passing adress2
  // Some extra tests:
  (testspace) = vtss_state_2;   // extra Test: pass the adress to a test pointer 
  testspace_ptr = &testspace;   // extra Test: pass the adress to a test pointer 
  (*testspace_ptr) = vtss_state_2;  // extra Test: pass the adress to a test pointer 
  vtss_state_2->a = 22;     // extra Test: change content of test pointer  
  printf ("\r\n\ta=22? a=%d ", (*inst)->a); //

}

/******************************************************************************
                           main
*******************************************************************************/


int
main ()
{
  // **The main structure:
  vtss_state_t state_test;
  state_test.a = 1234;      // pass some test value
  // **pointer to type of vtss_state_t
  vtss_inst_t inst;
  // **pass the adress of the structure!:
  inst = &state_test;

  // Test: add a value to a structure of the structure:
  // (is the same like inst->)
  state_test.u.x = 123;
  // Test: 
  inst->chip_count = 888;

  vtss_inst_get (inst);
  // Test:  I declared two global structure to test global access:
  printf ("\ntestspace points to: %d", testspace);
  printf ("\ntestspace ptr points to: %d", testspace_ptr);
  // Test variable a: 
  printf ("\n1234? inst->a=%d", inst->a);
  // Test: show value of structure in a strucure:
  printf ("\n123? state_test.u.x=%d", state_test.u.x);
  // Test: before & after address is changed:
  printf ("\r\n * Before create(): Adress  inst:%d", inst);
  printf ("\r\n******* Before create():chip_count: %d", inst->chip_count);
  vtss_inst_create (&inst);
  printf ("\r\n\n * After create(): Adress of inst:%d", inst);

  printf ("\r\n\t 22? a:%d", inst->a);
  printf
    ("\r\n even the layer2 function in create() worked:\n port_count=1?: %d",
     inst->port_count);

  printf
    ("\r\n\n\n******* chip_count has changes correctly to 12121: %d\n\n\n",
     inst->chip_count);
  //extra tests with the global structures:
  printf ("\ntestspace points to: %d", testspace);
  printf ("\n  testspace has the correct value a: %d", testspace->a);
  printf ("\n  testspace_ptr has the correct value a:: %d",
      (*testspace_ptr)->a);
  printf ("\n adress of pointer testspace_ptr points to?:%d", testspace_ptr);

// extra test:
  vtss_inst_get (inst);
  printf ("\n there is even access to a:%d", inst->a);


  printf ("\nPE-Hello World");


  return 0;
}

第二部分:VS Code下ARM Cortex M3平台测试

需要修改chip_count值,但调用库函数vtss_inst_create时无法生效,库函数代码如下:

vtss_rc vtss_inst_create(const vtss_inst_create_t *const create, vtss_inst_t *const inst, void (*print)(void))
{
    vtss_state_t *vtss_state;
    vtss_state             = malloc(sizeof(*vtss_state));
    vtss_state->chip_count = 777;
    (*inst)                = vtss_state;   
    // 后续函数逻辑省略
}

main中调用方式:vtss_inst_create(&create, &inst);
在main中读取chip_count的代码:

sprintf(t2, "\r\n main: chipcount should be 777 %d ??", (int)(inst->chip_count));
print_uart(t2);       

打印结果为482531848,为异常值。

之后仿写了多个同逻辑的测试函数,均正常工作:

  1. 单参数测试函数:
void createtest2(vtss_inst_t *const inst)
{
    vtss_state_t *vtss_state;
    vtss_state             = malloc(sizeof(*vtss_state));
    vtss_state->chip_count = 888;
    (*inst)                = vtss_state;
}

调用createtest2(&inst);后,读取chip_count值为888,正常。
2. 全参数对齐测试函数:

vtss_rc vtss_inst_create3(const vtss_inst_create_t *const create, vtss_inst_t *const inst, void (*print)(void))
{
    vtss_state_t *vtss_state;
    vtss_state             = malloc(sizeof(*vtss_state));
    vtss_state->chip_count = 222;
    (*inst)                = vtss_state;
    (void)create;
    (void)print;

    return 1;
}

调用vtss_inst_create3(&create, &inst, spitest);后,读取chip_count值为222,正常。

只有原库函数无法正常修改chip_count的值,排查发现之前曾修改过库函数的参数列表,新增了一个测试参数,该库函数位于其他独立文件中,即使改回原参数列表问题依然存在。进一步排查发现,同个结构体的cookie成员可以正常修改,仅chip_count成员无法修改,怀疑是CMAKE配置关闭了过多编译警告,屏蔽了潜在错误,运行时才暴露问题,CMAKE编译选项配置如下:

add_target_compile_flags(base PRIVATE "" "-Wno-unused-parameter" "-Wno-pedantic" "-Wno-format" "-Wno-sign-conversion" "-Wno-switch-default" "-Wno-conversion" "-Wno-unused-variable" "-Wno-undef" "-Wno-unused-but-set-variable" "-Wno-unused-function" "-Wno-implicit-function-declaration" "-Wno-uninitialized") 

问题根因排查方向

  • 头文件定义不一致:库函数所在编译单元引用的vtss_state_s结构体定义和main函数所在编译单元引用的定义不一致,比如内存对齐参数不同、chip_count的偏移量计算错误,导致修改的地址和实际读取的地址不是同一个位置
  • 函数声明不匹配:修改过库函数参数后没有同步更新对外的头文件声明,加上编译选项关闭了-Wimplicit-function-declaration,编译器不会报错,会默认函数返回int类型,调用时参数入栈规则不匹配,导致传参异常,inst指针指向错误地址
  • 内存越界:库函数malloc之后有其他代码逻辑写越界,覆盖了chip_count所在的内存地址,而cookie成员在结构体中位置靠前,没有被覆盖所以值正常
  • malloc失败:嵌入式环境下堆空间不足,malloc返回NULL,没有做判空处理,导致对空指针的偏移地址赋值,读取时拿到的是随机内存值

内容的提问来源于stack exchange,提问作者t1fpga1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 12:45:04