首先,对任何交叉发布表示歉意。希望我没有在这里重复这个问题,但我无法在其他地方找到这个问题(通过 Google 和 Stack Overflow)。
这是错误的要点。如果我在代码中的任何位置调用 printf
、sprintf
或 fprintf
来显示浮点数,我会收到 SIGSEGV (EXC_BAD_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
语句出现在代码的后面。
我之所以包含 malloc
内容,是因为据我了解,SIGSEGV
与格式不良的 malloc
调用有关。因此,如果数组初始化是导致问题的原因,我想知道:
- 为什么?
- 如何更改
malloc
代码来解决此问题?
我已经包含了 OS X 生成的崩溃日志,以防万一可以帮助任何人。
Process: pole [5453]
Path: {REDACTED}
Identifier: pole
Version: ??? (???)
Code Type: X86-64 (Native)
Parent Process: bash [5441]
Date/Time: 2009-12-08 11:38:38.358 -0600
OS Version: Mac OS X 10.6.2 (10C540)
Report Version: 6
Interval Since Last Report: 130074 sec
Crashes Since Last Report: 68
Per-App Crashes Since Last Report: 63
Anonymous UUID: CA20CF15-8C46-4C85-A793-6C69F9F40140
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000100074f3b
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 libSystem.B.dylib 0x00007fff828d489e __Balloc_D2A + 164
1 libSystem.B.dylib 0x00007fff828d49b8 __d2b_D2A + 45
2 libSystem.B.dylib 0x00007fff828e8c74 __dtoa + 320
3 libSystem.B.dylib 0x00007fff828aa960 __vfprintf + 4980
4 libSystem.B.dylib 0x00007fff828ec7db vfprintf_l + 111
5 libSystem.B.dylib 0x00007fff828ec75e fprintf + 196
6 pole 0x00000001000028b5 Balance::sarsa() + 187
7 pole 0x0000000100002e54 main + 49
8 pole 0x00000001000010a8 start + 52
Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000001 rbx: 0x000000010042cca0 rcx: 0x000000010042cca8 rdx: 0x0000000100074f3b
rdi: 0x000000000000000e rsi: 0x00007fff5fbfecbc rbp: 0x00007fff5fbfeba0 rsp: 0x00007fff5fbfeb90
r8: 0x00007fff5fbff0b0 r9: 0x0000000000000000 r10: 0x00000000ffffffff r11: 0x000000010083a40b
r12: 0x0000000000000001 r13: 0x00007fff5fbfecb8 r14: 0x00007fff5fbfecbc r15: 0x000000010000363e
rip: 0x00007fff828d489e rfl: 0x0000000000010202 cr2: 0x0000000100074f3b
Binary Images:
0x100000000 - 0x100003fff +pole ??? (???) {REDACTED}
0x7fff5fc00000 - 0x7fff5fc3bdef dyld 132.1 (???) /usr/lib/dyld
0x7fff81697000 - 0x7fff8169bff7 libmathCommon.A.dylib ??? (???) /usr/lib/system/libmathCommon.A.dylib
0x7fff8289c000 - 0x7fff82a5aff7 libSystem.B.dylib ??? (???) /usr/lib/libSystem.B.dylib
0x7fff83c4c000 - 0x7fff83cc9fef libstdc++.6.dylib ??? (???) /usr/lib/libstdc++.6.dylib
0x7fffffe00000 - 0x7fffffe01fff libSystem.B.dylib ??? (???) /usr/lib/libSystem.B.dylib
Model: MacBookPro4,1, BootROM MBP41.00C1.B03, 2 processors, Intel Core 2 Duo, 2.4 GHz, 2 GB, SMC 1.27f2
Graphics: NVIDIA GeForce 8600M GT, GeForce 8600M GT, PCIe, 256 MB
Memory Module: global_name
AirPort: spairport_wireless_card_type_airport_extreme (0x14E4, 0x8C), Broadcom BCM43xx 1.0 (5.10.91.19)
Bluetooth: Version 2.2.4f3, 2 service, 1 devices, 1 incoming serial ports
Network Service: AirPort, AirPort, en1
Serial ATA Device: Hitachi HTS542520K9SA00, 186.31 GB
Parallel ATA Device: MATSHITADVD-R UJ-867
USB Device: Built-in iSight, 0x05ac (Apple Inc.), 0x8502, 0xfd400000
USB Device: Apple Internal Keyboard / Trackpad, 0x05ac (Apple Inc.), 0x0230, 0x5d200000
USB Device: IR Receiver, 0x05ac (Apple Inc.), 0x8242, 0x5d100000
USB Device: BRCM2046 Hub, 0x0a5c (Broadcom Corp.), 0x4500, 0x1a100000
USB Device: Bluetooth USB Host Controller, 0x05ac (Apple Inc.), 0x820f, 0x1a110000
谢谢。
First and foremost, apologies for any cross-posting. Hope I'm not repeating an issue here, but I was unable to find this elsewhere (via Google and Stack Overflow).
Here's the gist of the error. If I call printf
, sprintf
or fprintf
anywhere within my code, to display a float, I get a SIGSEGV (EXC_BAD_ACCESS)
error. Let me give an example.
The following throws the error:
float f = 0.5f;
printf("%f\n",f);
This code does not:
float f = 0.5f;
printf("%d\n",f);
I realize there's an implicit conversion there, but I'm not concerned with that. I just can't fathom why printing a float vs. printing an integer would throw an error.
Note: Part of the code uses malloc
to create some very large multidimensional arrays. However, these arrays are not being referenced in any way for these print statements. Here's an example how I'm declaring these arrays.
#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;
}
And then the above printf
statements occur later in the code.
The reason I included the malloc
stuff is because from what I understand, SIGSEGV
is related to poorly formed malloc
calls. So, if the array initializations are what's causing the problem, I would like to know:
- why?
- how can I change the
malloc
code to solve this problem?
I've included the crash log generated by OS X, just in case that helps anybody out.
Process: pole [5453]
Path: {REDACTED}
Identifier: pole
Version: ??? (???)
Code Type: X86-64 (Native)
Parent Process: bash [5441]
Date/Time: 2009-12-08 11:38:38.358 -0600
OS Version: Mac OS X 10.6.2 (10C540)
Report Version: 6
Interval Since Last Report: 130074 sec
Crashes Since Last Report: 68
Per-App Crashes Since Last Report: 63
Anonymous UUID: CA20CF15-8C46-4C85-A793-6C69F9F40140
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000100074f3b
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 libSystem.B.dylib 0x00007fff828d489e __Balloc_D2A + 164
1 libSystem.B.dylib 0x00007fff828d49b8 __d2b_D2A + 45
2 libSystem.B.dylib 0x00007fff828e8c74 __dtoa + 320
3 libSystem.B.dylib 0x00007fff828aa960 __vfprintf + 4980
4 libSystem.B.dylib 0x00007fff828ec7db vfprintf_l + 111
5 libSystem.B.dylib 0x00007fff828ec75e fprintf + 196
6 pole 0x00000001000028b5 Balance::sarsa() + 187
7 pole 0x0000000100002e54 main + 49
8 pole 0x00000001000010a8 start + 52
Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000001 rbx: 0x000000010042cca0 rcx: 0x000000010042cca8 rdx: 0x0000000100074f3b
rdi: 0x000000000000000e rsi: 0x00007fff5fbfecbc rbp: 0x00007fff5fbfeba0 rsp: 0x00007fff5fbfeb90
r8: 0x00007fff5fbff0b0 r9: 0x0000000000000000 r10: 0x00000000ffffffff r11: 0x000000010083a40b
r12: 0x0000000000000001 r13: 0x00007fff5fbfecb8 r14: 0x00007fff5fbfecbc r15: 0x000000010000363e
rip: 0x00007fff828d489e rfl: 0x0000000000010202 cr2: 0x0000000100074f3b
Binary Images:
0x100000000 - 0x100003fff +pole ??? (???) {REDACTED}
0x7fff5fc00000 - 0x7fff5fc3bdef dyld 132.1 (???) /usr/lib/dyld
0x7fff81697000 - 0x7fff8169bff7 libmathCommon.A.dylib ??? (???) /usr/lib/system/libmathCommon.A.dylib
0x7fff8289c000 - 0x7fff82a5aff7 libSystem.B.dylib ??? (???) /usr/lib/libSystem.B.dylib
0x7fff83c4c000 - 0x7fff83cc9fef libstdc++.6.dylib ??? (???) /usr/lib/libstdc++.6.dylib
0x7fffffe00000 - 0x7fffffe01fff libSystem.B.dylib ??? (???) /usr/lib/libSystem.B.dylib
Model: MacBookPro4,1, BootROM MBP41.00C1.B03, 2 processors, Intel Core 2 Duo, 2.4 GHz, 2 GB, SMC 1.27f2
Graphics: NVIDIA GeForce 8600M GT, GeForce 8600M GT, PCIe, 256 MB
Memory Module: global_name
AirPort: spairport_wireless_card_type_airport_extreme (0x14E4, 0x8C), Broadcom BCM43xx 1.0 (5.10.91.19)
Bluetooth: Version 2.2.4f3, 2 service, 1 devices, 1 incoming serial ports
Network Service: AirPort, AirPort, en1
Serial ATA Device: Hitachi HTS542520K9SA00, 186.31 GB
Parallel ATA Device: MATSHITADVD-R UJ-867
USB Device: Built-in iSight, 0x05ac (Apple Inc.), 0x8502, 0xfd400000
USB Device: Apple Internal Keyboard / Trackpad, 0x05ac (Apple Inc.), 0x0230, 0x5d200000
USB Device: IR Receiver, 0x05ac (Apple Inc.), 0x8242, 0x5d100000
USB Device: BRCM2046 Hub, 0x0a5c (Broadcom Corp.), 0x4500, 0x1a100000
USB Device: Bluetooth USB Host Controller, 0x05ac (Apple Inc.), 0x820f, 0x1a110000
Thanks.
发布评论
评论(7)
您的代码中其他地方存在与
printf
语句无关的错误。您在某处占用了内存,但直到printf
尝试使用__BAlloc_D2A
分配一些内存时,问题才显现出来,这会崩溃,因为它使用的堆数据结构跟踪已损坏的空闲内存块。要尝试检测您在哪些地方占用了内存,可以使用多种工具。如果您使用的是 Linux,我建议使用 valgrind,它本质上是在虚拟机中运行您的代码,并在您需要时告诉您做任何非法的事情,例如越界读/写内存、读取未初始化的变量等。但是,它在 Mac OS X 中尚不可用。
一种选择是使用 libgmalloc:
另请参阅启用 Malloc 调试功能。
You have a bug elsewhere in your code not related to the
printf
statement. You're stomping on memory somewhere, but the problem doesn't manifest itself untilprintf
tries to allocate some memory with__BAlloc_D2A
, which crashes because the heap data structures it uses to keep track of free memory blocks have been corrupted.To try to detect where you're stomping on memory, there are a number of tools available. If you were on Linux, I would suggest using valgrind, which essentially runs your code in a virtual machine and tells you whenever you do anything illegal like read/write memory out of bounds, read an uninitialized variable, etc. However, it's not available in Mac OS X (yet).
One option is to use libgmalloc:
See also Enabling the Malloc Debugging Features.
当您访问未映射到任何内容的虚拟地址或以不允许的方式访问地址(例如,尝试写入只读区域)时,会发生 SIGSEGV。正如您所说,分段错误可能与堆损坏有关。这是因为在内部,大多数
malloc
实现将簿记信息与堆上分配的数据交错。如果簿记信息被损坏,malloc
的行为将不确定。直到程序的后期,您可能才会看到任何错误。在这种情况下,printf 可能会在内部分配一些内存,从而触发故障。解决此问题的最佳方法可能是使用 valgrind 运行程序,一旦发生任何堆损坏,它将通知您。
SIGSEGV occurs either when you access a virtual address that is not mapped to anything or when you access an address in a way which is not allowed (e.g., trying to write to a read-only area). As you say, segmentation faults can be related to heap corruption. This is because internally, most
malloc
implementations interleave bookkeeping information with allocated data on the heap. If that bookkeeping information gets corrupted,malloc
's behavior is undefined. You may not see any errors until much later in the program.In this case,
printf
is probably allocating some memory internally, which is triggering the fault. Probably the best way to fix this is to run your program with valgrind, which will notify you of any heap corruption as soon as it happens.您可能会遇到指针算术错误或缓冲区溢出,从而产生破坏 printf 的副作用。
尝试注释掉大部分代码(除了
printf
)并查看它是否崩溃。如果没有,则逐渐取消注释部分,直到崩溃恢复。看完你就知道问题出在哪里了。另外,如果您使用的是 Linux 或任何 Unix 变体,请考虑使用 valgrind 。
编辑:
我在您的错误报告中看到了这一点:
这就是实际崩溃的地方,这似乎是一个低级分配例程。我猜你有一个缓冲区溢出,它破坏了空闲列表,导致某些未来的分配中断(例如在此 printf 中)。
it is possible that you have a pointer arithmetic error or a buffer overflow which has the side effect of breaking the
printf
.Try commenting out the majority of the code (except the
printf
) and see if it crashes. If it doesn't, then little by little un-\comment parts until you get the crash back. The you'll know where the problem is.Also, if you are using linux or any unix variant, look into using valgrind as well.
EDIT:
I see this in your error report:
That's where the actual crash is, which appears to be a low level allocation routine. I would guess that you have a buffer overflow which is corrupting the free list, making certain future allocations break (such as in this printf).
第一个可能性是,您只是简单地 malloc() 为数组分配了足够的内存,而 printf() 尝试再 malloc() 一点,但失败了。我认为这是极不可能的。
第二个可能性是您的 printf() 并不像您显示的那么简单,而是一些相当复杂的多级指针表达式,并且该表达式在某个地方变得疯狂。
Possibility number one is that you are just plain malloc()'ing enough memory for your arrays that the printf() attempts to malloc() a little more,and fails. I think this is highly unlikely.
Possibility number two is that your printf() is not as simple as you are showing, but rather is some rather complicated multilevel pointer expression, and that expression is going wild somewhere.
printf 的某些实现在处理“%f”时会进行 malloc。如果它这样做,那么如果您在某个时刻内存溢出(即在分配结束后写入),则 printf 可以尝试进行分配并发现堆损坏并抛出错误......
只是一个想法。
编辑:可能值得看看你的状态数组是如何填充的......另外两个看起来不错,但你可能会在任何地方写到最后......
Some implementations of printf do a mallocs when processing "%f"s. If it IS doing this then if you have overflowed memory at some point (ie written past the end of the allocation) the printf can then try and make an allocation and find the heap corrupted and throw an error ...
just a thought.
Edit: Its probably worth looking at how your state array is filled ... the other 2 appear fine but you could be writing past the end anywhere ...
printf("%f", parm)
期望参数为双精度型。您的f
是一个浮点数,它会隐式转换为双精度数。也许隐式转换搞砸了???
尝试显式转换
,甚至
printf("%f", parm)
expects the parameter to be a double. Yourf
is a float which gets implicitly converted to a double.Maybe the implicit conversion is messed up ???
Try an explicit conversion
or even
只是猜测,但是您完成了
#include
吗?如果范围内没有malloc()
原型,编译器就会假定malloc()
返回int
,这显然是不正确的。如果我是对的(即使不是),它揭示了不在 C 中转换
malloc()
返回值的原因。请注意,如果您正在为 C 和 C++ 编写代码,则需要,但对于纯 C,不要强制转换malloc()
的返回值,并让编译器为您做正确的事情。因此,不要: 而是
这样做:
这里,
T
是任何类型。优点是:#include
,编译器会报错,data
的类型,malloc()
调用不需要改变,而且通过转换
malloc()
的返回值,编译器不会有机会警告您缺少stdlib.h
的包含。Just a guess, but have you done
#include <stdlib.h>
? Without a prototype formalloc()
in scope, the compiler assumes thatmalloc()
returnsint
, which is obviously not true.If I am right (even otherwise), it exposes a reason for not casting the return value of
malloc()
in C. Note that if you are writing code for both C and C++, you will need to, but for pure C, don't cast the return value ofmalloc()
, and let the compiler do the right thing for you.So, instead of:
do this instead:
Here,
T
is any type. The advantages are:#include <stdlib.h>
,data
, themalloc()
call doesn't need to change, andBy casting the return value of
malloc()
, you don't give the compiler a chance to warn you about missing inclusion ofstdlib.h
.