編輯:找到的解決方案(參見下圖)Strsep我的Mac OS X x86_64系統上就返回一個32位指針
我試圖構建一個軟件包(owfs)在Mac OS X 10.8 x86_64的系統上。這個軟件包大部分是在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,這是我找到的。進入初始化path_segment
與strsep
通話,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
TIP) 做多一點挖後,我發現問題是編譯器標誌-D_POSIX_C_SOURCE=200112L
。此編譯器標誌阻止了strsep的定義,從而使編譯器進行了隱式聲明。我從配置腳本中刪除了這一切,似乎一切正常。謝謝您的幫助!
是否違規編譯單元'#include'?如果是這樣,cc -E |是什麼grep strsep'顯示'strsep'被聲明爲? –
user4815162342
使用'gcc -I./module/owlib/src/include -I/opt/local/include -I./src/include -E module/owlib/src/c/ow_alias.c | grep strsep',我得到strsep聲明爲'char * strsep(char **,const char *);',這看起來是正確的。但是在完整的Make過程中,我在編輯上面得到編譯器警告...... – bencpeters