分段错误,大小为4的无效写入

米尔顿·席尔瓦(Milton Silva)

我有以下结构:

typedef struct ann_t {
  uint32_t xs;
  uint32_t hs;
  uint32_t ys;
  float *x;
  float *h;
  float *y;
  float **wxh;
  float **why;
} ann_t;

通过以下方式初始化:

ann_t* ann_init(uint32_t xs, uint32_t hs, uint32_t ys) {
  ann_t *ann = malloc(sizeof(ann_t));
  ann->xs = xs;
  ann->hs = hs;
  ann->ys = ys;
  ann->x = calloc(xs, sizeof(float));
  ann->h = calloc(hs, sizeof(float));
  ann->y = calloc(ys, sizeof(float));

  
  ann->wxh = calloc(xs, sizeof(float*));
  ann->why = calloc(hs+1, sizeof(float*));

  
  int i, j;
  for(i = 0; i < xs; i++) {
    ann->wxh[i] = malloc(hs * sizeof(float));
  }

  for(i = 0; i < hs+1; i++) {
    ann->why[i] = malloc(ys * sizeof(float));
  }
  // printf("%p\n", ann->x);
  return ann;
}

将此代码包含在另一个程序中:

  ...

  ann_t *ann = ann_init(25, 10, 4);
  // printf("%p\n", ann->x);
  ann->x[0] = 1.0;

  ...

结果是:

分段故障(核心已转储)

使用valgrind:

== 26436 ==使用大小为8的未初始化值

...

== 26436 ==

== 26436 ==大小为4的无效写入

...

== 26436 ==地址0x4c3a78000000000未堆栈,未分配或(最近)释放

我试图在一个较小的程序中重现它,但是没有。

更改结构以拥有uint64_t而不是uint32_t解决问题。

ann->x内部打印指针ann_init我得到0x55601051f080和在外部0x1051f08000000000

为什么会这样?

编辑:在其中一个文件中找到了罪魁祸首:

#pragma pack(1)

仍然不确定为什么这会导致问题。

如果我正在执行指针算术来访问struct字段,这是有道理的,但是我正在按名称访问struct字段,那么为什么它计算出错误的值?

为什么在init函数内部没问题,但在外部访问失败?

埃德·英格利斯

从对问题的评论中得出的答案...

假设您在标头中定义了一个更简单的结构:

// header.h
typedef struct {
  char foo;
  int *ptr;
} fish_t;

和两个源文件:

// src1.c
#include "header.h"

int dummy_int = 5;

fish_t my_fish;
my_fish.foo = 'a';
my_fish.ptr = &dummy_int;

use_fish_fn( &my_fish );
// src2.c
#pragma pack(1)
#include "header.h"

void use_fish_fn( fish_t *f )
{
  int bar = *f->ptr;
}

第一个文件(不带包装)可能看起来fish_t像是这样的内存布局:

0: |  foo  |  pad  |  pad  |  pad  |     // one byte char, three bytes padding
4: |              ptr              |     // four byte pointer

但是第二个文件(带有包装)如下所示:

0: |  foo  |        ptr ...        |     // one byte char, 3/4 of pointer
4: |...ptr |                             // last part of pointer

因此,当第二个文件尝试读取(然后取消引用)指针时,它实际上是在读取填充中碰巧的所有内容,这肯定会出错。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C分段错误,大小为4的读取无效

来自分类Dev

c Valgrind读取大小4无效->分段错误

来自分类Dev

Valgrind大小为8的神秘无效写入错误

来自分类Dev

我简化了项目的一部分,以解决我遇到的这个具体问题(无效写入大小4 /分段错误)

来自分类Dev

大小为4的读取无效

来自分类Dev

Valgrind错误:使用由struct和malloc构成的列表时,大小为8的无效写入

来自分类Dev

使用Valgrind在C中无效读取大小8的分段错误

来自分类Dev

Valgrind-strcpy的大小为1的无效写入

来自分类Dev

Valgrind 错误无效读取大小 4

来自分类Dev

分段错误-无效的内存引用

来自分类Dev

java.lang.IndexOutOfBoundsException:无效的索引1,在分段RecyclerView中,大小为1

来自分类Dev

ListAdapter错误:IndexOutOfBoundsException:无效的索引0,大小为0

来自分类Dev

Valgrind中大小为4的无效读/写

来自分类Dev

为什么Valgrind在PETSc中分配char *时报告大小写为8的无效写入?

来自分类Dev

写入新WAV时出现分段错误

来自分类Dev

写入文件时出现C分段错误

来自分类Dev

大小8的无效读取,大小8(Valgrind)的无效写入

来自分类Dev

FFMPEG MOV到MP4错误{无法为输出文件#0写入标题(编解码器参数不正确?):无效的参数}

来自分类Dev

写入sysfs的“ echo:写入错误:无效的参数”

来自分类Dev

数组的最大大小 - 分段错误

来自分类Dev

free() 中的错误:大小无效

来自分类Dev

Android适配器“ java.lang.IndexOutOfBoundsException:无效的索引4,大小为4”

来自分类Dev

C-错误为“ free():下一个大小无效(正常)”

来自分类Dev

C:将 4 个字节写入大小为 3 的区域是否会溢出目标?

来自分类Dev

为交换功能获取分段错误 11

来自分类Dev

尝试重新分配内存时“大小为 4 的无效读取”

来自分类Dev

bash:回显:写入错误:无效的参数

来自分类Dev

解决 valgrind 中的无效写入错误

来自分类Dev

sed 和 tac:写入错误:参数无效

Related 相关文章

  1. 1

    C分段错误,大小为4的读取无效

  2. 2

    c Valgrind读取大小4无效->分段错误

  3. 3

    Valgrind大小为8的神秘无效写入错误

  4. 4

    我简化了项目的一部分,以解决我遇到的这个具体问题(无效写入大小4 /分段错误)

  5. 5

    大小为4的读取无效

  6. 6

    Valgrind错误:使用由struct和malloc构成的列表时,大小为8的无效写入

  7. 7

    使用Valgrind在C中无效读取大小8的分段错误

  8. 8

    Valgrind-strcpy的大小为1的无效写入

  9. 9

    Valgrind 错误无效读取大小 4

  10. 10

    分段错误-无效的内存引用

  11. 11

    java.lang.IndexOutOfBoundsException:无效的索引1,在分段RecyclerView中,大小为1

  12. 12

    ListAdapter错误:IndexOutOfBoundsException:无效的索引0,大小为0

  13. 13

    Valgrind中大小为4的无效读/写

  14. 14

    为什么Valgrind在PETSc中分配char *时报告大小写为8的无效写入?

  15. 15

    写入新WAV时出现分段错误

  16. 16

    写入文件时出现C分段错误

  17. 17

    大小8的无效读取,大小8(Valgrind)的无效写入

  18. 18

    FFMPEG MOV到MP4错误{无法为输出文件#0写入标题(编解码器参数不正确?):无效的参数}

  19. 19

    写入sysfs的“ echo:写入错误:无效的参数”

  20. 20

    数组的最大大小 - 分段错误

  21. 21

    free() 中的错误:大小无效

  22. 22

    Android适配器“ java.lang.IndexOutOfBoundsException:无效的索引4,大小为4”

  23. 23

    C-错误为“ free():下一个大小无效(正常)”

  24. 24

    C:将 4 个字节写入大小为 3 的区域是否会溢出目标?

  25. 25

    为交换功能获取分段错误 11

  26. 26

    尝试重新分配内存时“大小为 4 的无效读取”

  27. 27

    bash:回显:写入错误:无效的参数

  28. 28

    解决 valgrind 中的无效写入错误

  29. 29

    sed 和 tac:写入错误:参数无效

热门标签

归档