C SIGSEGV,(表面上)由printf引起

C SIGSEGV,(表面上)由printf引起,c,malloc,printf,segmentation-fault,C,Malloc,Printf,Segmentation Fault,首先,也最重要的是,为任何交叉发布道歉。希望我没有在这里重复一个问题,但我在别处找不到(通过谷歌和堆栈溢出) 以下是错误的要点。如果我在代码中的任何地方调用printf、sprintf或fprintf来显示浮点,我会得到一个SIGSEGV(EXC\u BAD\u ACCESS)错误。让我举个例子 下面将抛出错误: float f = 0.5f; printf("%f\n",f); 此代码不包括: float f = 0.5f; printf("%d\n",f); 我意识到这里有一个隐含的转换

首先,也最重要的是,为任何交叉发布道歉。希望我没有在这里重复一个问题,但我在别处找不到(通过谷歌和堆栈溢出)

以下是错误的要点。如果我在代码中的任何地方调用
printf
sprintf
fprintf
来显示浮点,我会得到一个
SIGSEGV(EXC\u BAD\u ACCESS)
错误。让我举个例子

下面将抛出错误:

float f = 0.5f;
printf("%f\n",f);
此代码不包括:

float f = 0.5f;
printf("%d\n",f);
我意识到这里有一个隐含的转换,但我不关心这个。我就是不明白为什么打印浮点数和打印整数会出错

注意:部分代码使用
malloc
创建一些非常大的多维数组。但是,这些打印语句不会以任何方式引用这些数组。下面是我如何声明这些数组的示例

#define X_LEN 20
#define XDOT_LEN 20
#define THETA_LEN 20
#define THETADOT_LEN 20
#define NUM_STATES (X_LEN+1) * (XDOT_LEN+1) * (THETA_LEN+1) * (THETADOT_LEN+1)
#define NUM_ACTS 100

float *states = (float *)malloc(NUM_STATES * sizeof(float));
// as opposed to float states[NUM_STATES] (more memory effecient)


float **q = (float**)malloc(NUM_STATES * sizeof(float*));

for(int i=0; i < NUM_STATES; i++) {
    float *a = (float*)malloc(NUM_ACTS * sizeof(float));
    for(int j=0; j < NUM_ACTS; j++) {
        a[j] = 0.0f;
    }
    q[i] = a;
}

谢谢。

可能是指针算术错误或缓冲区溢出,其副作用是破坏
printf

试着注释掉大部分代码(除了
printf
),看看它是否崩溃。如果没有,则一点一点地取消对部分的注释,直到您恢复崩溃。你会知道问题出在哪里

另外,如果您使用的是linux或任何unix变体,也要考虑使用

编辑:

我在您的错误报告中看到:

0   libSystem.B.dylib               0x00007fff828d489e __Balloc_D2A + 164

这就是实际崩溃的地方,这似乎是一个低级别的分配例程。我猜您的缓冲区溢出正在破坏空闲列表,导致某些未来的分配中断(例如在这个printf中)。

第一种可能性是您只是简单地为数组分配了足够的内存,printf()尝试多分配一点malloc(),但失败了。我认为这是极不可能的


第二种可能性是printf()并不像您所展示的那么简单,而是一个相当复杂的多级指针表达式,当您访问未映射到任何内容的虚拟地址或以不允许的方式访问地址(例如,尝试写入只读区域)时,就会出现SIGSEGV。正如您所说,分段错误可能与堆损坏有关。这是因为在内部,大多数
malloc
实现将簿记信息与堆上分配的数据交织在一起。如果簿记信息损坏,
malloc
的行为未定义。您可能在程序中很晚之后才会看到任何错误


在这种情况下,
printf
可能正在内部分配一些内存,从而触发故障。修复此问题的最佳方法可能是使用valgrind运行程序,一旦发生堆损坏,valgrind将立即通知您

printf的某些实现在处理“%f”时会执行mallocs。如果正在这样做,那么如果在某个点内存溢出(即在分配结束后写入),printf可以尝试进行分配,发现堆已损坏并抛出错误

只是一个想法

编辑:可能值得一看你的状态数组是如何填充的。。。其他2个看起来很好,但您可以在任何地方写入结束处。

printf(“%f”,parm)
希望参数为双精度。您的
f
是一个浮点,隐式转换为双精度

也许隐式转换搞砸了

尝试显式转换

float f = 0.5f;
printf("%f\n",(double)f);
甚至

float f = 0.5f;
double ff = f;
printf("%f\n",ff);

代码中的其他地方有一个与
printf
语句无关的bug。您正在某个地方踩踏内存,但直到
printf
尝试使用
\uu BAlloc\u D2A
分配一些内存时,问题才显现出来,这会崩溃,因为它用来跟踪空闲内存块的堆数据结构已损坏

为了尝试检测内存的占用位置,有很多可用的工具。如果你在Linux上,我建议使用,它基本上是在虚拟机上运行你的代码,并告诉你什么时候你做了非法的事情,比如读/写内存越界,读一个未初始化的变量,等等。但是,它在Mac OS X中还不可用

一种选择是使用:

%cat gmalloctest.c
#包括
#包括
main()
{
无符号*缓冲区=(无符号*)malloc(sizeof(无符号)*100);
未签名的i;
对于(i=0;i<200;i++){
缓冲区[i]=i;
}
对于(i=0;i<200;i++){
printf(“%d”,缓冲区[i]);
}
}
%cc-g-o gmalloctest gmalloctest.c
%gdb gmalloctest
正在读取共享库的符号。。完成
(gdb)设置env DYLD_INSERT_LIBRARIES/usr/lib/libgmalloc.dylib
(gdb)r
启动程序:gmalloctest
正在读取共享库的符号。。完成
GuardMalloc:分配将放置在16字节的边界上。
GuardMalloc:-可能没有注意到某些缓冲区溢出。
GuardMalloc:-使用矢量指令(如SSE或Altivec)的应用程序应该可以工作。
GuardMalloc:GuardMalloc版本19
程序接收到信号EXC_访问错误,无法访问内存。
原因:地址0xb000d000处的内核保护失败
gmalloctest.c:10处的主()中的0x00001f65
10缓冲区[i]=i;
(gdb)打印i
$1 = 100
(gdb)在哪里
#gmalloctest.c处的main()中0 0x00001f65:10
(gdb)

另请参见。

只是一个猜测,但是您是否已经完成了
\include
?如果范围中没有
malloc()
的原型,编译器会假定
malloc()
返回
int
,这显然是错误的

如果我是正确的(甚至相反),它会暴露出一个不在C中转换“代码> MalCube()/<代码>的返回值的原因。注意,如果您正在编写C和C++的代码,则需要,但是对于纯C,不要将返回值<代码> MalCube())/代码>,并让编译。

float f = 0.5f;
double ff = f;
printf("%f\n",ff);
% cat gmalloctest.c
#include <stdlib.h>
#include <stdio.h>

main()
{
  unsigned *buffer = (unsigned *)malloc(sizeof(unsigned) * 100);
  unsigned i;

  for (i = 0; i < 200; i++) {
    buffer[i] = i;
  }

  for (i = 0; i < 200; i++) {
     printf ("%d  ", buffer[i]);
  }
}

% cc -g -o gmalloctest gmalloctest.c
% gdb gmalloctest
Reading symbols for shared libraries .. done
(gdb) set env DYLD_INSERT_LIBRARIES /usr/lib/libgmalloc.dylib
(gdb) r
Starting program: gmalloctest
Reading symbols for shared libraries .. done
GuardMalloc: Allocations will be placed on 16 byte boundaries.
GuardMalloc:  - Some buffer overruns may not be noticed.
GuardMalloc:  - Applications using vector instructions (e.g., SSE or Altivec) should work.
GuardMalloc: GuardMalloc version 19

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0xb000d000
0x00001f65 in main () at gmalloctest.c:10
10          buffer[i] = i;
(gdb) print i
$1 = 100
(gdb) where
#0  0x00001f65 in main () at gmalloctest.c:10
(gdb)
T *data = (T *) malloc(sz * sizeof(T));
#include <stdlib.h>
...
T *data = malloc(sz * sizeof *data);