[英]Strsep returns a 32 bit pointer on my Mac OS X x86_64 system
编辑:找到解决方案(请参阅底部)
我正在尝试在Mac OS X 10.8 x86_64系统上构建软件包( owfs )。 这个软件包主要是在Linux上/针对Linux开发的,但是我已经有了一个旧版本,可以正确地编译和运行,并且人们在运行各种版本的互联网上发布了很多文章,所以我希望这是可能的。 。 我已经能够成功完成编译过程,但是当我尝试运行该程序时,该程序会出现段错误。 我在GDB中进行了调查,结果如下:
令人讨厌的代码段:
void FS_dir_entry_aliased(void (*dirfunc) (void *, const struct parsedname *), void *v, const struct parsedname *pn)
{
if ( ( pn->state & ePS_unaliased ) == 0 ) {
// Want alias substituted
struct parsedname s_pn_copy ;
struct parsedname * pn_copy = & s_pn_copy ;
ASCII path[PATH_MAX+3] ;
ASCII * path_pointer = path ; // current location in original path
// Shallow copy
memcpy( pn_copy, pn, sizeof(struct parsedname) ) ;
pn_copy->path[0] = '\0' ;
// path copy to use for separation
strcpy( path, pn->path ) ;
// copy segments of path (delimitted by "/") to copy
while( path_pointer != NULL ) {
ASCII * path_segment = NULL;
path_segment = strsep( &path_pointer, "/" ) ;
BYTE sn[SERIAL_NUMBER_SIZE] ;
if ( PATH_MAX < strlen(pn_copy->path) + strlen(path_segment) ) {
由于path_segment
是越界地址,因此在if
块中对strlen(path_segment)
的调用失败。
我发现了与GDB分步进行的工作。 进入用strsep
初始化path_segment
的调用,gdb给了我:
path_pointer = (ASCII *) 0x7fff5fbf99a5 "/uncached/bus.0/interface"
我执行下一行之后, path_pointer
前进了,就像我期望的那样:
path_pointer = (ASCII *) 0x7fff5fbf99a6 "uncached/bus.0/interface"
但是gdb报告:
path_segment = (ASCII *) 0x5fbf99a5 <Address 0x5fbf99a5 out of bounds>
这是地址的正确“开始”,但它是32位指针地址。 由于我的系统是64位系统,因此在调用strlen
时,我得到一个EXC_BAD_ACCESS。
我知道这里发生了很多事情,如果问题是软件包构建过程中深层隐患的话,我还没有提供足够的信息。 在我看来,这可能有一个简单的解决方案,因为该函数基本上可以正常工作,但是只是返回了错误的大小指针。 我对64位和32位系统的复杂性经验很少,所以我想知道是否有人可以发现明显的东西,或者提供调试此问题的后续步骤的说明。 有趣的是,当我在gdb( p (ASCII *) strsep (&path_pointer, "/")
)中手动运行strsep
命令时,它们似乎运行良好,为我提供了与我期望的相匹配的64位指针。
最后,如果有用,我相信这是strsep调用的组装线:
0x0000000100036eee <FS_dir_entry_aliased+318>: callq 0x1000a56a0 <dyld_stub_strsep>
0x0000000100036ef3 <FS_dir_entry_aliased+323>: mov %eax,%ecx
0x0000000100036ef5 <FS_dir_entry_aliased+325>: movslq %ecx,%rcx
0x0000000100036ef8 <FS_dir_entry_aliased+328>: mov %rcx,-0x1d10(%rbp)
并针对位于该callq地址的strsep进行反汇编:
0x00007fff915c0fc7 <strsep+0>: push %rbp
0x00007fff915c0fc8 <strsep+1>: mov %rsp,%rbp
0x00007fff915c0fcb <strsep+4>: mov (%rdi),%r8
0x00007fff915c0fce <strsep+7>: xor %eax,%eax
0x00007fff915c0fd0 <strsep+9>: test %r8,%r8
0x00007fff915c0fd3 <strsep+12>: je 0x7fff915c1007 <strsep+64>
0x00007fff915c0fd5 <strsep+14>: mov %r8,%r10
0x00007fff915c0fd8 <strsep+17>: jmp 0x7fff915c0fe4 <strsep+29>
0x00007fff915c0fda <strsep+19>: inc %rdx
0x00007fff915c0fdd <strsep+22>: test %al,%al
0x00007fff915c0fdf <strsep+24>: jne 0x7fff915c0fee <strsep+39>
0x00007fff915c0fe1 <strsep+26>: mov %r9,%r10
0x00007fff915c0fe4 <strsep+29>: mov (%r10),%cl
0x00007fff915c0fe7 <strsep+32>: lea 0x1(%r10),%r9
0x00007fff915c0feb <strsep+36>: mov %rsi,%rdx
0x00007fff915c0fee <strsep+39>: mov (%rdx),%al
0x00007fff915c0ff0 <strsep+41>: cmp %cl,%al
0x00007fff915c0ff2 <strsep+43>: jne 0x7fff915c0fda <strsep+19>
0x00007fff915c0ff4 <strsep+45>: xor %edx,%edx
0x00007fff915c0ff6 <strsep+47>: test %cl,%cl
0x00007fff915c0ff8 <strsep+49>: je 0x7fff915c1001 <strsep+58>
0x00007fff915c0ffa <strsep+51>: movb $0x0,(%r10)
0x00007fff915c0ffe <strsep+55>: mov %r9,%rdx
0x00007fff915c1001 <strsep+58>: mov %rdx,(%rdi)
0x00007fff915c1004 <strsep+61>: mov %r8,%rax
0x00007fff915c1007 <strsep+64>: pop %rbp
0x00007fff915c1008 <strsep+65>: retq
编辑:肯定会包含string.h,有一个包含它的系统范围的包含文件,但只是为了确保我尝试将其添加到此特定文件中。 -D_BSD_SOURCE=1
是自动添加的编译器选项之一,因此正在发生。 默认情况下,还有一个编译器选项-D_ISOC99_SOURCE=1
。 我尝试添加-std=gnu99
(我的编译器llvm-gcc 4.2,不喜欢-std=gnu90
),但没有解决。 我收到以下编译器错误:
这是我为此文件得到的编译器警告:
ow_alias.c: In function 'ReadAliasFile':
ow_alias.c:40: warning: implicit declaration of function 'getline'
ow_alias.c:48: warning: implicit declaration of function 'strsep'
ow_alias.c:48: warning: assignment makes pointer from integer without a cast
ow_alias.c:64: warning: assignment makes pointer from integer without a cast
ow_alias.c: In function 'FS_dir_entry_aliased':
ow_alias.c:177: warning: initialization makes pointer from integer without a cast
第二次编辑:经过更多的挖掘(感谢gcc -E | grep strsep
提示!),我发现问题出在编译器标志-D_POSIX_C_SOURCE=200112L
。 该编译器标志阻止了strsep的定义,从而使编译器进行隐式声明。 我从配置脚本中删除了它,似乎一切正常。 谢谢您的帮助!
您需要确保包含string.h
。
如果已经完成,则还需要定义一个功能测试宏以启用strsep()
的声明。 添加-D_GNU_SOURCE
或-D_BSD_SOURCE
应该可以解决问题。 但是,您可能想研究一下如何配置事物_BSD_SOURCE
通常默认情况下_BSD_SOURCE
启用状态。 也许您是在告诉gcc使用-std=c90
或-std=c99
进行编译,这将关闭许多功能测试宏。 请改用-std=gnu90
或-std=gnu99
。
您是否看到诸如“初始化使指针从整数而不进行强制转换”或“函数的隐式声明”之类的警告?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.