简体   繁体   English

Strsep在我的Mac OS X x86_64系统上返回32位指针

[英]Strsep returns a 32 bit pointer on my Mac OS X x86_64 system

Edit: Found solution (see bottom) 编辑:找到解决方案(请参阅底部)

I'm trying to build a software package ( owfs ) on a Mac OS X 10.8 x86_64 system. 我正在尝试在Mac OS X 10.8 x86_64系统上构建软件包( owfs )。 This software package is mostly developed on/for linux, but I've gotten an old version to compile and function correctly, and there are plenty of posts around the internet of people running various versions of it, so I'm hopeful that it's possible. 这个软件包主要是在Linux上/针对Linux开发的,但是我已经有了一个旧版本,可以正确地编译和运行,并且人们在运行各种版本的互联网上发布了很多文章,所以我希望这是可能的。 。 I've been able to get the compilation process to complete successfully, but the program segfaults when I try to run it. 我已经能够成功完成编译过程,但是当我尝试运行该程序时,该程序会出现段错误。 I investigated in GDB, and here is what I found: 我在GDB中进行了调查,结果如下:

The offending piece of code: 令人讨厌的代码段:

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) ) {

The call to strlen(path_segment) in the if block fails because path_segment is an out-of-bounds address. 由于path_segment是越界地址,因此在if块中对strlen(path_segment)的调用失败。

Taking things step by step with GDB, here's what I've found. 我发现了与GDB分步进行的工作。 Going into the call that initializes path_segment with strsep , gdb gives me: 进入用strsep初始化path_segment的调用,gdb给了我:

path_pointer = (ASCII *) 0x7fff5fbf99a5 "/uncached/bus.0/interface"

After I execute the next line, path_pointer has advanced, as I would expect: 我执行下一行之后, path_pointer前进了,就像我期望的那样:

path_pointer = (ASCII *) 0x7fff5fbf99a6 "uncached/bus.0/interface"

but gdb reports: 但是gdb报告:

path_segment = (ASCII *) 0x5fbf99a5 <Address 0x5fbf99a5 out of bounds>

This is the correct "start" of the address, but it's a 32-bit pointer address. 这是地址的正确“开始”,但它是32位指针地址。 Since my system is a 64-bit system, when strlen gets called on this, I get a EXC_BAD_ACCESS. 由于我的系统是64位系统,因此在调用strlen时,我得到一个EXC_BAD_ACCESS。

I understand there's a lot going on here, and I haven't provided enough info if the problem is something buried deeply in the package build process. 我知道这里发生了很多事情,如果问题是软件包构建过程中深层隐患的话,我还没有提供足够的信息。 It seems to me though that this might have a simple solution, since the function is basically working correctly, but just returning the wrong size pointer. 在我看来,这可能有一个简单的解决方案,因为该函数基本上可以正常工作,但是只是返回了错误的大小指针。 I have very little experience with the intricacies of 64 bit vs. 32 bit systems though, so I was wondering if anyone can spot something obvious, or provide instructions for next steps debugging this issue. 我对64位和32位系统的复杂性经验很少,所以我想知道是否有人可以发现明显的东西,或者提供调试此问题的后续步骤的说明。 Interestingly, when I run the strsep commands by hand in gdb ( p (ASCII *) strsep (&path_pointer, "/") ), they appear to work fine, giving me 64 bit pointers that match what I expect them to. 有趣的是,当我在gdb( p (ASCII *) strsep (&path_pointer, "/") )中手动运行strsep命令时,它们似乎运行良好,为我提供了与我期望的相匹配的64位指针。

Finally, in case it's useful, here's what I believe are the assembly lines for the strsep call: 最后,如果有用,我相信这是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)

and the disassemble for the strsep that's at that callq address: 并针对位于该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

Edit: string.h is definitely being included, there's a system-wide include file that includes it, but just to make sure I tried adding it this specific file. 编辑:肯定会包含string.h,有一个包含它的系统范围的包含文件,但只是为了确保我尝试将其添加到此特定文件中。 -D_BSD_SOURCE=1 is one of the compiler options added automatically, so that is happening. -D_BSD_SOURCE=1是自动添加的编译器选项之一,因此正在发生。 There is also a compiler option -D_ISOC99_SOURCE=1 by default. 默认情况下,还有一个编译器选项-D_ISOC99_SOURCE=1 I tried adding -std=gnu99 (my compiler, llvm-gcc 4.2, doesn't like -std=gnu90 ), but it did not fix it. 我尝试添加-std=gnu99 (我的编译器llvm-gcc 4.2,不喜欢-std=gnu90 ),但没有解决。 I'm getting the following compiler errors: 我收到以下编译器错误:

Here are the compiler warnings that I get for this file: 这是我为此文件得到的编译器警告:

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

Second Edit: After doing a little more digging (thanks for the gcc -E | grep strsep tip!), I found the problem was with a compiler flag -D_POSIX_C_SOURCE=200112L . 第二次编辑:经过更多的挖掘(感谢gcc -E | grep strsep提示!),我发现问题出在编译器标志-D_POSIX_C_SOURCE=200112L This compiler flag was blocking the definition of strsep, making the compiler make an implicit declaration. 该编译器标志阻止了strsep的定义,从而使编译器进行隐式声明。 I removed this from the configure script and everything seems to be working fine. 我从配置脚本中删除了它,似乎一切正常。 Thanks for the help! 谢谢您的帮助!

You need to make sure that string.h is included. 您需要确保包含string.h

If that's already being done, you'll need to also define a feature test macro to enable the declaration of strsep() . 如果已经完成,则还需要定义一个功能测试宏以启用strsep()的声明。 Adding -D_GNU_SOURCE or -D_BSD_SOURCE should do the trick. 添加-D_GNU_SOURCE-D_BSD_SOURCE应该可以解决问题。 However, you might want to look into how you have things configured right now - _BSD_SOURCE is usually enabled by default. 但是,您可能想研究一下如何配置事物_BSD_SOURCE通常默认情况下_BSD_SOURCE启用状态。 Perhaps you're telling gcc to compile with -std=c90 or -std=c99 , which will turn off many feature test macros. 也许您是在告诉gcc使用-std=c90-std=c99进行编译,这将关闭许多功能测试宏。 Use -std=gnu90 or -std=gnu99 instead. 请改用-std=gnu90-std=gnu99

Are you seeing warnings such as "initialization makes pointer from integer without a cast" or "implicit declaration of function"? 您是否看到诸如“初始化使指针从整数而不进行强制转换”或“函数的隐式声明”之类的警告?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM